在查找根节点,我们需要一个一个查找parent以得到这个集合的根节点。
那么我们在查找的时候,如果父节点不是根节点的话,可以指向父节点的父节点,这样就节省了不少树的高度(非递归版)。
- 当然,因为节点是有指向父节点的,所以可以让每一个都指向根节点,根节点可以有无数个孩子(递归版)。
- 理论上,递归版树的高度要低点,效率好,但是实际上,由于递归过程会产生额外的开销~
实际中,使用非递归的就可以了,面试的时候讲讲非递归的~
// 查找过程, 查找元素p所对应的集合编号
// O(h)复杂度, h为树的高度
private int find(int p){
assert( p >= 0 && p < count );
// path compression 1
while( p != parent[p] ){
parent[p] = parent[parent[p]];
p = parent[p];
}
return p;
// path compression 2, 递归算法
// if( p != parent[p] )
// parent[p] = find( parent[p] );
// return parent[p];
}
路径压缩中,不需要维护rank了吗?
事实上,这就是把这个变量叫做rank而不叫height的原因。引入压缩路径,维护深度就变得困难了。
实际上,rank只是我们一个标志当前节点排名的一个数字,在压缩中,尽管rank高的点被抬上来了,但是每个集合的rank都相对的抬上来了,还是可以做一个参考的~