并查集——路径压缩

  • 关于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)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值