并查集(Union-Find Set)小结

做了几道并查集的题,在这里做一个小小的总结,以表达我对这个精简的数据结构的浅显的理解。。。

先说说用途:
1、并查集,顾名思义分为并和查。
并:即:将两个完全不相交的集合合并为一个集合。
查:查询某个元素属于哪一个集合,一般用来判断两个元素是否属于同一集合。
2、目前我所接触到的它的实际用途:
(1)、求解最小生成树(克鲁斯卡尔算法)
(2)、判断图是否连通或是否有环
(3)、确定无向图的连通子图个数
(4)、确定某一集合或者团体有多少元素(或个体)。

接下来就说说并查集的三种操作(三个函数):
1、Make_Set(x):把每一个元素初始化为一个集合。
初始化后每一个元素的父亲节点是它本身,每一个元素的祖先节点也是它本身(也可以根据情况而变)。
2、GetParent(x) :查找一个元素所在的集合。
其精髓是找到这个元素所在集合的祖先!这个才是并查集判断和合并的最终依据。判断两个元素是否属于同一集合,只要看他们所在集合的祖先是否相同即可。
3、Merge(x,y):合并x,y所在的两个集合
合并两个不相交集合操作很简单:
利用GetParent函数找到这两个集合的祖先,将一个集合的祖先指向另一个集合的祖先。

对于并查集的优化,一个是路径压缩,一个是按秩合并,这也是这个数据结构的精髓所在和最为优美的地方。

直接看代码:

int parent[MAX];   /* father[x]表示x的父节点*/
int rank[MAX];     /* rank[x]表示x的秩*/
// 初始化集合
void Make_Set(int x)
{
    parent[x] = x; //根据实际情况指定的父节点可变化
    rank[x] = 0;  //根据实际情况初始化秩也有所变化
}
// 查找x元素所在的集合,回溯时压缩路径
int GetParent(int a){
  if(parent[a]!=a)
    parent[a]=GetParent(parent[a]); //这个回溯时的压缩路径是精华
  return parent[a];
}
/* 
   按秩合并x,y所在的集合
   下面的那个if else结构不是绝对的,具体根据情况变化
   但是,宗旨是不变的即,按秩合并,实时更新秩。
*/
void Merge(int x, int y)
{
    x = GetParent(x);
    y = GetParent(y);
    if (x == y) return;
    if (rank[x] > rank[y]) 
    {
        parent[y] = x;
    }
    else
    {
        if (rank[x] == rank[y])
        {
            rank[y]++;
        }
        parent[x] = y;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值