数据结构笔记--实现简单并查集算法

1--并查集算法

        并查集的核心功能有两个:第一个是判断两个元素是否属于同一个集合;第二个是合并两个元素,使其处在同一集合中;

#include <iostream>
#include <list>
#include <stack>
#include <unordered_map>

class UnionFindSet{
public:
    // 初始化并查集,每个结点的所在集合的代表结点是其本身
    UnionFindSet(std::list<int> nums){
        for(int node : nums){
            father_map.emplace(node, node);
        }
    }

    // 寻找结点的代表结点
    int FindFather(int node1){
        std::stack<int> stk;
        while(father_map[node1] != node1){
            stk.push(node1);
            node1 = father_map[node1]; 
        }
        while(!stk.empty()){
            int tmp = stk.top();
            stk.pop();
            father_map[tmp] = node1;
        }
        return node1;
    }

    // 判断是否是一个集合
    bool isSameSet(int node1, int node2){
        if(father_map.find(node1) == father_map.end() || father_map.find(node2) == father_map.end()){
            return false; // 结点不存在
        }

        // 具有相同的代表结点
        if(FindFather(node1) == FindFather(node2)) return true;

        return false;
    }

    // 合并两个元素
    void Union(int node1, int node2){
        // 已经属于一个集合了
        if(isSameSet(node1, node2)) return; 
        // 找到两个集合的代表结点
        int father1 = FindFather(node1); 
        int father2 = FindFather(node2);
        // 将一个集合的结点指向另一个集合的代表结点
        father_map[father1] = father2;
    }

private:
    std::unordered_map<int, int> father_map; // key表示结点,value表示结点的父亲(集合的代表结点)
};

int main(int argc, char * argv[]){
    std::list<int> test = {1, 2, 3};
    UnionFindSet S1(test);
    bool res1 = S1.isSameSet(1, 2);
    if (res1){
        std::cout << "true" << std::endl; 
    }
    else std::cout << "false" << std::endl;

    S1.Union(1, 2);
    bool res2 = S1.isSameSet(1, 2);
    if (res2){
        std::cout << "true" << std::endl; 
    }
    else std::cout << "false" << std::endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43863869/article/details/132454959