并查集-(union-find sets)

10 篇文章 0 订阅

在某些应用,要将n个不同元素分成一组不相交的集合,并且在各些集合上要提供两个操作,一个实查找一个元素所属的集合另一个操作是合并两个集合。应用有求一个图的连通分量个数。还有Kruscal算法中判断是否出现环。 其实并查集数据结构非常简单, 下面介绍的版本考虑了优化。 因为可能出现如下图所示的情况:



在这做图的情况下查找一个点所属的集合的时间复杂度是O(n),就失去并查集说具有的高效性。因此在查找的时候递归找到祖先节点,在回溯的时候将子孙节点直接指向祖先节点,如右图所示。下面给出并查集算法的三个核心函数:


 1int father[MAX];   /* father[x]表示x的父节点*/
 2int rank[MAX];     /* rank[x]表示x的秩*/
 3
 4
 5/* 初始化集合*/
 6void Init(int x)
 7{
 8    father[x] = x; //根据实际情况指定的父节点可变化
 9    rank[x] = 0;   //根据实际情况初始化秩也有所变化
10}

11
12
13/* 查找x元素所在的集合,回溯时压缩路径*/
14int Find(int x)
15{
16    if (x != father[x])
17    {
18        father[x] = Find(father[x]); //这个回溯时的压缩路径是精华
19    }

20    return father[x];
21}

22
23
24/* 
25   按秩合并x,y所在的集合
26   下面的那个if else结构不是绝对的,具体根据情况变化
27   但是,宗旨是不变的即,按秩合并,实时更新秩。
28*/

29void Union(int x, int y)
30{
31    x = Find(x);
32    y = Find(y);
33    if (x == y) return;
34    if (rank[x] > rank[y]) 
35    {
36        father[y] = x;
37    }

38    else
39    {
40        if (rank[x] == rank[y])
41        {
42            rank[y]++;
43        }

44        father[x] = y;
45    }

46}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值