zoukankan      html  css  js  c++  java
  • 并查集(一)理解

    并查集(union-¯nd set) 维护一些不相交的集合,它是一个集合的集合。每个元素

    恰好属于一个集合,好比每条鱼装在一个鱼缸里。每个集合S有一个元素作为\集合代

    表"rep[S],好比每个鱼缸选出一条"鱼王"。并查集提供三种操作:

    MakeSet(x):建立一个新集合xx应该不在现有的任何一个集合中出现。

    Find(S, x):返回x所在集合的代表元素。

    Union(x, y):把x所在的集合和y所在的集合合并。

    森林表示法

    可以用一棵森林表示并查集,森林里的每棵树表示一个集合,树根就

    是集合的代表元素。一个集合还可以用很多种树表示,只要树中的结点不变,表示的

    都是同一个集合。

    合并操作

    只需要将一棵树的根设为另一棵即可。这一步显然是常数的。一个优化

    是:把小的树合并到大树中,这样会让深度不太大。这个优化称为启发式合并。

    查找操作

    只需要不断的找父亲,根就是集合代表。一个优化是把沿途上所有结点

    的父亲改成根。这一步是顺便的,不增加时间复杂度,却使得今后的操作比较快。这个优化称为路径压缩,

    实现代码

    用p[i] 表示i 的父亲,而rank[i] 表示i 的秩,并用秩来

    代替深度做刚才提到的启发式合并。

    void makeset(int x)

    {

        p[x]=x;

        rank[x]=0;

    }

    int findset(int x)

    {

        if(x!=p[x])

        p[x]=findset(p[x]);

        return p[x];

    }

    //////   使用非递归的更好理解

    int findset ( int x)
    {
    int px = x , i;
    while (px != p[px ]) px = p[px ]; // find root
    while (x != px ) // path compression
    {
    i = p[x];
    p[x ] = px;
    x = i;
    }
    return px;
    }

    void union_set(int x,int y)

    {

        x=findset(x);

        y=findset(y);

        if(rank[x]>rank[y])

        p[y]=x;

        else

            {

                p[x]=y;

                if(rank[x]==rank[y])rank[y]++;

    }

    }

  • 相关阅读:
    多层感知机的简洁实现
    汇编语言总结(1)
    回顾下TCP/IP协议
    五笔输入法的前世今生
    大O算法
    算法基础概念
    TCP和UDP的区别
    数据结构基本概念和术语
    gdb调试方法
    GD32F20x系列使用问题总结
  • 原文地址:https://www.cnblogs.com/sachin/p/2691520.html
Copyright © 2011-2022 走看看