并查集的定义、Union、Find 及优化

//实现并查集的数据结构定义,并实现 Union、Find 两个基本操作
#define SIZE 13
int UFSets[SIZE];		//用一个数组表示并查集

//初始化并查集
void Initial(int S[]) {  //S即为并查集
    for (int i = 0; i < SIZE; i++)  //每个自成单元素集合
        S[i] = -1;
}

//Find “查”操作,找x所属集合(返回x所属根结点)
/*判断两个元素是否属于同一集合,只需分别找到他们的根,比较是否相同即可*/
int Find(int S[], int x) {
    while (S[x] >= 0)			//循环寻找x的根
        x = S[x];
    return x;						//根的S[]小于0
}

//Union “并”操作,将两个集合合并为一个
/*求两个不相交子集合的并集,需先找到两个元素的根,再令一棵子集树的根指向另一棵子集树的根*/
void Union(int S[], int Root1, int Root2) {
    if (Root1 == Root2)	return;  //要求Root1与Root2是不同的集合
    S[Root2] = Root1;   //将根Root2连接到另一根Root1下面
}

//可采取“小树合并到大树”的策略优化 Union操作
//Union “并”操作,小树合并到大树
/*极端情况下,n个元素构成的集合树深度为n,则find最坏时间复杂度为O(n)
  改进方法:在Union前,先判别子集中的成员数量,然后令成员少的根指向多的根(小树合并到大树)
  此外,根节点的绝对值保存集合树中成员数量,此方法深度不超过1+logn*/
void Union(int S[], int Root1, int Root2) {
    if (Root1 == Root2)	return;
    if (S[Root2] > S[Root1]) {	//Root2结点数更少
        S[Root1] += S[Root2];	//累加结点总数
        S[Root2] = Root1; //小树合并到大树
    }
    else {
        S[Root2] += S[Root1];	//累加结点总数
        S[Root1] = Root2; //小树合并到大树    		 
    }
}

//可采取“路径压缩”的策略优化 Find 操作
//Find “查”操作优化,先找到根节点,再进行“压缩路径”
/*随着子集的合并,集合树深度越来越大,为减少查找时间,现对Find优化
  优化方案:当所查元素x不在树的第二层时,在算法中增加一个“压缩路径”的功能
  此功能可将根到元素x路径上的所有元素都变成根的孩子*/
int Find(int S[], int x) {
    int root = x;
    while (S[root] >= 0)  root = S[root]; //循环找到根
    while (x != root) {	//压缩路径
        int t = S[x];		//t指向x的父节点
        S[x] = root;		//x直接挂到根节点下
        x = t;              //循环
    }
    return root;						//返回根节点编号
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值