C++ 并查集(Union-Find Sets)

一、实现程序:

#include 
using namespace std;

struct Node { // 并查集结点类
    int data; // 保存数据
    int parent; // 保存父结点
};

class UnionFindSets {
public:
    UnionFindSets(int w[], int n); // 构造函数
    ~UnionFindSets(); // 析构函数
    void Union(int a, int b); // 并
    bool Find(int a, int b); // 查找两个数是否在同一集合
private:
    Node *s; // 数组
    int currentSize; // 实际存储的个数
    int Find(int x); // 查找x,并返回x的根结点
};

// 构造函数
UnionFindSets::UnionFindSets(int w[], int n) {
    // 初始化
    currentSize = n;
    s = new Node[n];
    for(int i = 0; i < n; i++) {
        s[i].data = w[i];
        s[i].parent = -1;
    }
}

// 析构函数
UnionFindSets::~UnionFindSets() {
    delete []s; // 释放空间
}

// 并
void UnionFindSets::Union(int a, int b) {
    int root1, root2;
    
    root1 = Find(a); // 找到a的根结点
    root2 = Find(b); // 找到b的根结点
    if(root1 == root2 || root1 == -1 || root2 == -1) // 根结点相同,或者其中一个数不在集合中
        return;
    if(s[root1].parent < s[root2].parent) // 说明root1的树高比root2的树高大
        s[root2].parent = root1;
    else if(s[root1].parent == s[root2].parent) { // 树高相等
        s[root2].parent = root1;
        s[root1].parent = s[root1].parent - 1; // root1的树高变高,因为是负数,所以减1
    } else { // root2的树高比root1的树高大
        s[root1].parent = root2;
    }
}

// 查找两个数是否在同一集合
bool UnionFindSets::Find(int a, int b) {
    int root1, root2;
    
    root1 = Find(a); // 查找a的根结点
    root2 = Find(b);
    if(root1 != root2) // 根结点不同,说明不在同一集合
        return false;
    return true; // 在同一集合,返回true
}

// 查找x,并返回x的根结点
int UnionFindSets::Find(int x) {
    int i;
    
    for(i = 0; i < currentSize && s[i].data != x; i++); // 在数组中查找
    if(i >= currentSize) // 没找到
        return -1;
    for(; s[i].parent >= 0; i = s[i].parent); //  找根结点
    return i;
}

int main(int argc, const char * argv[]) {
    int w[] = {3, 8, 10, 1, 5, 4}, choice, a, b;
    int len = sizeof(w)/sizeof(w[0]); // 数组的长度
    bool finished = false;
    
    UnionFindSets uf(w, len); // 创建并查集对象
    while(!finished) {
        cout << "[1]并" << endl;
        cout << "[2]查" << endl;
        cout << "[3]退出" << endl;
        cout << "请输入你的选择[1-3]:";
        cin >> choice;
        switch(choice) {
            case 1:
                cout << "请输入两个要进行并运算的元素:" << endl;
                cin >> a >> b;
                uf.Union(a, b); // 并
                break;
            case 2:
                cout << "请输入两个要检查是否在同一集合的元素:" << endl;
                cin >> a >> b;
                if(uf.Find(a, b)) // 是
                    cout << "Yes" << endl;
                else // 否
                    cout << "No" << endl;
                break;
            case 3:
                finished = true;
                break;
            default:
                cout << "输入错误,请重新输入!" << endl;
        }
    }
    return 0;
}

测试结果:

C++ 并查集(Union-Find Sets)_第1张图片

C++ 并查集(Union-Find Sets)_第2张图片

你可能感兴趣的:(数据结构)