美文网首页
并查集的C++实现

并查集的C++实现

作者: book_02 | 来源:发表于2022-01-10 17:00 被阅读0次

这里只写了实现和应用。

理论部分可以参考下面的链接:
https://zh.wikipedia.org/wiki/%E5%B9%B6%E6%9F%A5%E9%9B%86
https://www.runoob.com/data-structures/union-find-basic.html

1. C++实现

  1. 并查集实现是可以分为有rank和无rank。
  2. 有rank的实现在合并的时候,把rank小的挂在rank大的上面,一定程度上能提高效率。
  3. 无rank代码稍微简单一些,看起来比较清晰

1.1 有rank

合并的时候,把rank小的挂在rank大的上面,一定程度上能提高效率

class UnionFindSet {
public:
    UnionFindSet(int num_vertex) {
        num_vertex_ = num_vertex;
        father_     = vector<int>(num_vertex_);
        rank_       = vector<int>(num_vertex_);
    }

private:
    void make_set() {               //初始化集合,让所有的点都各成一个集合,每个集合都只包含自己
        for (int i = 0; i < num_vertex_; i++) {
            father_[i] = i;
            rank_[i] = 1;
        }
    }

    int find_set(int x) {           //判断一个点属于哪个集合,点如果都有着共同的祖先结点,就可以说他们属于一个集合
        if (x != father_[x]) {
            father_[x] = find_set(father_[x]);
        }
        return father_[x];
    }

    void union_set(int x, int y) {  //将x,y合并到同一个集合
        x = find_set(x);
        y = find_set(y);

        if (x == y) { return; }

        if (rank_[x] < rank_[y]) {
            father_[x] = find_set(y);
        }
        else {
            if (rank_[x] == rank_[y]) { rank_[x]++; }

            father_[y] = find_set(x);
        }
    }

    int             num_vertex_;
    vector<int>     father_;
    vector<int>     rank_;
};

1.2 无rank

class UnionFindSetNoRank {
public:
    UnionFindSetNoRank(int num_vertex) {
        num_vertex_ = num_vertex;
        father_ = vector<int>(num_vertex_);
        make_set();
    }
    
    void make_set() {               //初始化集合,让所有的点都各成一个集合,每个集合都只包含自己
        for (int i = 0; i < num_vertex_; i++) {
            father_[i] = i;
        }
    }

    int find_set(int x) {           //判断一个点属于哪个集合,点如果都有着共同的祖先结点,就可以说他们属于一个集合
        if (x != father_[x]) {
            father_[x] = find_set(father_[x]);
        }
        return father_[x];
    }

    void union_set(int x, int y) {  //将x,y合并到同一个集合
        x = find_set(x);
        y = find_set(y);

        if (x == y) { return; }

        father_[y] = x;
    }

private:
    int             num_vertex_;
    vector<int>     father_;
};

下面的实现跟上面一样,只是函数名使用驼峰命名法,上面的是下划线分割法

class UnionFindSetNoRank {
public:
    UnionFindSetNoRank(int num_vertex) {
        num_vertex_ = num_vertex;
        father_ = vector<int>(num_vertex_);
        makeSet();
    }

    void makeSet() {               //初始化集合,让所有的点都各成一个集合,每个集合都只包含自己
        for (int i = 0; i < num_vertex_; i++) {
            father_[i] = i;
        }
    }

    int findSet(int x) {           //判断一个点属于哪个集合,点如果都有着共同的祖先结点,就可以说他们属于一个集合
        if (x != father_[x]) {
            father_[x] = findSet(father_[x]);
        }
        return father_[x];
    }

    void unionSet(int x, int y) {  //将x,y合并到同一个集合
        x = findSet(x);
        y = findSet(y);

        if (x == y) { return; }

        father_[y] = x;
    }

private:
    int             num_vertex_;
    vector<int>     father_;
};

2. 应用

leetcode 547. 省份数量
https://leetcode-cn.com/problems/number-of-provinces/

思路: 查找连通域的个数

class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        int N = isConnected.size();

        num_vertex_ = N;
        father_ = vector<int>(num_vertex_);
        rank_ = vector<int>(num_vertex_);
        make_set();

        for (int i = 0; i < N; ++i) {
            for (int j = 0; j < N; ++j) {
                if (isConnected[i][j]) {
                    union_set(i, j);
                }
            }
        }

        int count = 0;
        for (int i = 0; i < N; ++i) {
            if (father_[i] == i) {
                count++;
            }
        }

        return count;
    }

private:
    void make_set() {               //初始化集合,让所有的点都各成一个集合,每个集合都只包含自己
        for (int i = 0; i < num_vertex_; i++) {
            father_[i] = i;
            rank_[i] = 1;
        }
    }

    int find_set(int x) {           //判断一个点属于哪个集合,点如果都有着共同的祖先结点,就可以说他们属于一个集合
        if (x != father_[x]) {
            father_[x] = find_set(father_[x]);
        }
        return father_[x];
    }

    void union_set(int x, int y) {  //将x,y合并到同一个集合
        x = find_set(x);
        y = find_set(y);

        if (x == y) { return; }

        if (rank_[x] < rank_[y]) {
            father_[x] = find_set(y);
        }
        else {
            if (rank_[x] == rank_[y]) { rank_[x]++; }

            father_[y] = find_set(x);
        }
    }

    int             num_vertex_;
    vector<int>     father_;
    vector<int>     rank_;
};

相关文章

  • C++ 实现并查集

    并查集 并查集实际上就是并集和查集的过程。集(集合)可以理解为一棵树,即一个根结点连着无数个子节点。 例题解析 输...

  • 并查集的C++实现

    这里只写了实现和应用。 理论部分可以参考下面的链接:https://zh.wikipedia.org/wiki/%...

  • c++中并查集实现

    何谓并查集 并查集实际上就是并集和查集的过程。那么什么是集呢?你可以把他近似地理解为一棵树。即一个根结点连着无数个...

  • 数据结构与算法(十二)并查集(Union Find)

    本文主要包括以下内容: 并查集的概念 并查集的操作 并查集的实现和优化Quick FindQuick Union基...

  • 算法与数据结构系列之[并查集-中]

    上篇介绍了并查集的基本实现,这篇介绍几种并查集的优化方法。 1.基于size优化: 上一篇当中树实现并查集的方法中...

  • 并查集练习

    并查集 参考《算法笔记》 三要素:并,查,集。 并差集与一个算法有关,kruskal算法,就可通过并查集实现。 1...

  • LeetCode 分类刷题 —— Union Find

    Union Find 的 Tips: 灵活使用并查集的思想,熟练掌握并查集的模板,模板中有两种并查集的实现方式,一...

  • Golang实现并查集

    模拟C++实现了一个并查集,主要是理解连通图的原理。main.go utils/union_find_set.go...

  • 并查集的C++实现及优化

    前言 并查集(Disjoint-set) 的代码非常简洁,但是功能却很强大。关于并查集,这里有一篇文章超有爱的并查...

  • c++并查集配合STL的实现

    不会并查集的话请将此文与我以前写的并查集一同食用。原题来自洛谷原题文字稿在此: map map是STL中的一种数据...

网友评论

      本文标题:并查集的C++实现

      本文链接:https://www.haomeiwen.com/subject/bmomcrtx.html