您的位置:首页 > 其它

并查集——路径压缩

2017-09-25 11:11 253 查看
关于Rank的优化

上文中我们已经对代码进行了几次优化,使得进行连接操作的时候,所形成的树长度尽量短,但同时也存在另一种情况:集合元素多,但是每个元素分别指向根节点,这样就只有两层(举例),那么就应该把这棵树的根节点指向另一棵高树的根节点,就出现了所谓的“集合元素多,但是树长度短“的情况,因此,应当首先考虑树的高度而非树的元素量

进行如下优化:

class unionFind{

private:
int* parent;
int* rank;	//记录树的高度
int count;
public:
UnionFind(int count){
parent=new int[count];
rank=new int[count];
this->count=count;
for(int i=0;i<count;i++){
parent[i]=i;
rank[i]=1;   //初始高度都为1
}
}
~unionFind(){
delete [] parent;
delete [] rank;
}

int find(int p){
assert(p>=0&&p<count);
while(p!=parent[p])
p=parent[p];
return p;
}

bool isConnected(int p,int q){
return find(p)==find(q);
}

void unionElements(int p,int q){
int pRoot=find(p);
int qRoot=find(q);
if(pRoot==qRoot)
return;
if(rank[pRoot]<rank[qRoot]){   //两棵树一高一低,连接后高度与高树保持一致
parent[pRoot]=qRoot;
}
if(rank[pRoot]>rank[qRoot]){
parent[qRoot]=pRoot;
}
else{					//两棵树高度一样,连接后高度加一
parent[qRoot]=pRoot;
rank[qRoot]++;
}
}
};


路径压缩(Path Compression)

int find(int p){
if(p!=parent[p])
parent[p]=find(parent[p]);
return parent[p];
}


注意:递归会耗费一定时间,视情况选择路径压缩的程度。此种路径压缩完毕后,形成的是一棵高度为2的树,每个元素指向根节点。

相应地,也有一种不太彻底的路径压缩方法:

int find(int p){
assert(p>=0&&p<count);
while(p!=parent[p]){
parent[p]=parent[parent[p]];
p=parent[p];
}
return p;
}

并查集的时间复杂度近乎为O(1)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  并查集