并查集系列

并查集类似静态链表,使用数组实现,元素的值就是指针指向,即父结点。
每个集合中选出一个代表,这个代表就是这棵树中的根。

每个元素指向其父亲,根节点的值指向自己。


并查集树的表示


并查集的基本操作:
1.void makeSet(int s):建立一个并查集,其中包含s个单元素集合


2.int find(int x):其中x是指要查找的元素的index,结果返回x所属集合的代表
 这个代表告诉你它在哪个集合


 注意在find的时候要进行路径压缩,否则查找效率就是树的高度
 是log级别的而不是常数级了




3.void unionSet(int x,int y):合并两个元素所在的集合,就是将一个集合的代表指向
另一个集合的代表
合并有两种方案,两种方案都遵循弱肉强食的原则



非按秩合并:

const int MAXSIZE = 500;
int uset[MAXSIZE];
 
void makeSet(int size) {
    for(int i = 0;i < size;i++) uset[i] = -1;
}
int find(int x) {<span style="white-space:pre">	</span>//递归find
    if (uset[x] < 0) return x;
    uset[x] = find(uset[x]);
    return uset[x];
}
int find(int x) {
    int p = x, t;
    while (uset[p] >= 0) p = uset[p];
    while (x != p) {
        t = uset[x];
        uset[x] = p;
        x = t;
    }
    return x;
}
void unionSet(int x, int y) {
    if ((x = find(x)) == (y = find(y))) return;
    if (uset[x] < uset[y]) {
        uset[x] += uset[y];
        uset[y] = x;
    } else {
        uset[y] += uset[x];
        uset[x] = y;
    }
}

按秩合并


const int MAXSIZE = 500;
int uset[MAXSIZE];
int rank[MAXSIZE];

void makeSet(int size){
	for(int i = 0;i<size;i++)	uset[i] = i;
	memset(rank,0,sizeof(rank));
}


int find(int x){
	if(x!=uset[x])	uset[x] = find(uset[x]);
	return uset[x];				
}

void unionSet_1(int x,int y){
	if((x=find(x))==(y=find(y)))	
	if(rank[x]>rank[y])	uset[y] = x;	
										
	else{
		uset[x] = y;
		if(rank[x]==rank[y])	rank[y]++;	
	}
}





猜你喜欢

转载自blog.csdn.net/l_apple8/article/details/50704940
今日推荐