并查集
// 并查集—————
#define UFSets[SIZE]; //集合元素数组
//初始化并查集
void Initial(int S[]){
for(int i = 0; i < SIZE; i++) {
S[i] = -1;
}
}
//Find "查"操作,找x所属集合(返回x所属根结点)
//最坏空间复杂度: O(n)
int Find(int S[], int x){
while(S[x] >= 0) //循环找x的根
x = S[x];
return x; //根的S[]小于0
}
//Union "并"操作, 将两个集合合并为一个
//时间复杂度:O(1)
void Union(int S[], int Root1, int Root2){
//要求Root1与Root2是不同的集合
if(Roo1 == Root2) return;
//将根Root2连接到另一根Root1下面
S[Root2] = Root1;
}
// ————优化:Union: 小树合并到大树
//时间复杂度:O(1)
// 使树高不超过[log2n]+1
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 "查"操作优化,先找到根结点,再进行"压缩路径"
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; //返回根节点编号
}