《算法:C语言实现》——连通性

/* 主题: 连通性问题
 * 问题表述: 给定整数对的一个序列,其中每个整数表示某种类型的一个对象,我们想要说明对p-q表示“p链接到q”。
 *         “连通”关系是可传递的,即p-q,q-r,则p-r。我们的目标是写一个过滤集合中的无关对的程序。程序的
 *         输入为p-q,如果已经看到的到那点的数对并不隐含着p连通到q,那么输出该对。如果前面的对确实隐含
 *         着p连通到q,那么程序应该忽略p-q,并应该继续输入下一对。
 * 开发语言: C++
 * 编译器: g++
 * 作者: chinazhangjie
 * 邮箱: chinajiezhang@gmail.com
 * 参考书籍: 《算法: C语言实现(第1~4部分)》
 *
 * 测试数据:
 *  对象: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 *  边: 3-4, 4-9, 8-0, 2-3, 5-6, 2-9, 5-9, 7-3, 4-8, 5-6, 0-2, 6-1
 */

#include <iostream>
#include <vector>
#include <string>
#include <iterator>
using namespace std;

const int objectCount = 10;
const int lineCount = 12;

struct Line
{
    int left;
    int right;
public:
    Line (int l, int r) : left(l), right(r) {}
    Line () {}
};

void PrintObject(const vector<int> & object, const string& prompt = string(""));

// 快速查找算法。为了要与其他算法用一份源数据,所以在计算之前,复制一份数据
void QuickFind(const vector<int> & object, const vector<Line> & line)
{
    vector<int> aObject(object);  // a for assist
    vector<Line> aLine(line);

    for (int i=0; i<(int)aLine.size(); ++i) {
        if (aObject[aLine[i].left] == aObject[aLine[i].right]) continue;

        int temp = aObject[aLine[i].left];
        for (int j=0; j<(int)aObject.size(); ++j) {
            if (aObject[j] == temp) aObject[j] = aObject[aLine[i].right];
        }
    }
    PrintObject(aObject, "QuickFind");
}

// 快速合并算法
void QuickMerge(const vector<int> & object, const vector<Line> & line)
{
    vector<int> aObject(object);
    vector<Line> aLine(line);

    for (int i=0; i<(int)aLine.size(); ++i) {
        int j;
        int k;

        for (j=aObject[aLine[i].right]; j != aObject[j]; j = aObject[j]) ;
        for (k=aObject[aLine[i].left]; k != aObject[k]; k = aObject[k]) ;

        if (j == k) continue;
        aObject[k] = j;
    }

    PrintObject(aObject, string("QuickMerge"));
}

// 加权快速合并算法。增加一个数组记录每棵树的结点个数,每次合并的时候将较小的树连接到较大的树上,以防止树中长度路径的增长
void WeightedQuickMerge(const vector<int> & object, const vector<Line> & line)
{
    vector<int> aObject(object);
    vector<Line> aLine(line);
    vector<int> nodeCount(objectCount, 1);

    for (int i=0; i<(int)aLine.size(); ++i) {
        int j;
        int k;

        for (j=aObject[aLine[i].right]; j != aObject[j]; j = aObject[j]) ;
        for (k=aObject[aLine[i].left]; k != aObject[k]; k = aObject[k]) ;

        if (j == k) continue;

        if (nodeCount[j] < nodeCount[k]) {
            aObject[j] = k;
            nodeCount[j] += nodeCount[k];
        }
        else {
            aObject[k] = j;
            nodeCount[k] += nodeCount[j];
        }
    }

    PrintObject(aObject, string("WeightedQuickMerge"));
}

// 等分路径压缩
void SplitPathCompress(const vector<int> & object, const vector<Line> & line)
{
    vector<int> aObject(object);
    vector<Line> aLine(line);

    for (int i=0; i<(int)aLine.size(); ++i) {
        int j;
        int k;

        for (j=aObject[aLine[i].right]; j != aObject[j]; j = aObject[j]) {
            aObject[j] = aObject[aObject[j]];
        }
        for (k=aObject[aLine[i].left]; k != aObject[k]; k = aObject[k]) {
            aObject[k] = aObject[aObject[k]];
        }
    }

    PrintObject(aObject, string("SplitPathCompresse"));
}

// 打印数据
void PrintObject(const vector<int> & object, const string& prompt)
{
    cout << prompt << ": ";
    copy(object.begin(), object.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
}

int main()
{
    // init
    vector<int> object(objectCount);
    for (int i=0; i<objectCount; ++i) {
        object[i] = i;
    }
    vector<Line> line;
    line.push_back(Line(3, 4));
    line.push_back(Line(4, 9));
    line.push_back(Line(8, 0));
    line.push_back(Line(2, 3));
    line.push_back(Line(5, 6));
    line.push_back(Line(2, 9));
    line.push_back(Line(5, 9));
    line.push_back(Line(7, 3));
    line.push_back(Line(4, 8));
    line.push_back(Line(5, 6));
    line.push_back(Line(0, 2));
    line.push_back(Line(6, 1));

    //
    QuickFind(object, line);
    QuickMerge(object, line);
    WeightedQuickMerge(object, line);
    SplitPathCompress(object, line);
    return 0;
}

本文完

转载注明出处,谢谢!

2011-06-22

posted @ 2011-06-22 22:38 独酌逸醉 阅读(...) 评论(...) 编辑 收藏