• 并查集


    它最重要的作用就是用来:检查一个图是否存在环。

       

    #define VERTICES 6
    
    void Init(int parent[], int rank[])
    {
        for (int i = 0; i < VERTICES; ++i) {
            parent[i] = -1;
            rank[i] = 0;     // 代表当前树高
        }
    }
    
    int FindRoot(int x, int parent[])
    {
        int x_root = x;
        while (parent[x_root] != -1) {
            x_root = parent[x_root];
        }
        return x_root;
    }
    
    int Union(int x, int y, int parent[], int rank[])
    {
        int x_root = FindRoot(x, parent);
        int y_root = FindRoot(y, parent);
    
        if(x_root == y_root) {
            return 0;
        }
        else {
            // parent[x_root] = y_root;
            if ( rank[x_root] > rank[y_root] ) {
                parent[y_root] = x_root;
            }
            else if ( rank[x_root] < rank[y_root] ) {
                parent[x_root] = y_root;
            }
            else {
                parent[x_root] = y_root;
                ++rank;
            }
            return 1;
        }
    }
    
    int main()
    {
        int parent[VERTICES] = {0};
        int rank[VERTICES] = {0};
        int edges[6][2] = {
            {0, 1}, {1, 2}, {1, 3},
            {2, 4}, {3, 4}, {2, 5}
        };
    
        Init(parent, rank);
    
        for(int i = 0; i < 6; ++i) {
            int x = edges[i][0];
            int y = edges[i][1];
    
            if(Union(x, y, parent, rank) == 0) {
                printf("Cycle detected!
    ");
                exit(0);
            }
        }
    
        printf("No cycle found.
    ");
    
        return 0;
    }

    上面是一种路径压缩的思路,即根据 rank 数组,将较矮的树连接到较高的树上。

    也有另一种路径压缩的方法,如下

    int FindRoot(int x, int parent[])
    {
        int x_root = x;
    
        while( x != parent[x]) {
            x = parent[x];    // 此时 x 为根节点
        }
    
        // 进行路径压缩, 把所有非根节点的父节点都改为x
        while(-1 != parent[x_root])
        {
            int z = x_root;           // 先记录该节点
            x_root = parent[x_root];  // a指向父节点
            parent[z] = x;            // 修改子节点的父亲
        }
        return x;
    }
    
  • 相关阅读:
    0514JS基础:操作document对象、事件、this
    Java 多态
    Java 抽象类和接口
    Vue中v-for属性
    Vue基础语法
    Vue 自定义按键修饰符,自定义指令,自定义过滤器
    ES6 剩余参数
    ES6 箭头函数
    ES6 解构赋值
    ES6 变量声明 var let const的区别
  • 原文地址:https://www.cnblogs.com/yanghh/p/13703580.html
Copyright © 2020-2023  润新知