我正在考试这个星期天,我只想确认我所做的事情是否正确(你知道考试让我持怀疑态度)
这就是算法的工作原理:
int Find(int x)
{ // Return the set containing x and compress the path from x to root
// First, find the root
int z = x; while (P[z] > 0) { z = P[z]; } int root = z;
// Start at x again and reset the parent // of every node on the path from x to root z = x;
while (P[z] > 0)
{ int t = P[z];
P[z] = root; // Reset Parent of z to root
z = t; }
return root; }
这就是问题:
回想一下为不相交的Union-Find问题开发的算法 从一组n个元素中设置。 Find使用路径压缩和Union 使用排名。此外,同一级别的两棵树联盟选择了 root与第二个参数关联为新根。从集合S开始 = {1,2,...,10}和10个不相交的子集,每个子集包含一个元素。一个。执行后绘制最后一组树:
联盟(1,2),联盟(3,4),联盟(5,6),联盟(1,5),联盟(1,3)。
这是我对这个问题的解决方案:
我希望对此算法有任何提示或建议。
谢谢!
答案 0 :(得分:0)
Union-Find Set
的查找操作的关键点是 路径压缩 。
如果我们知道集合A的根是r1
,集合B的根是r2
,那么当连接集A并将B集合在一起时。最简单的方法是将集合B的根设置为集合A的根,这意味着father[r2] = r1;
但它不是那么“聪明”,当r2
的儿子,我们说x
,想知道它的根,x
问其父亲r2
,然后父亲r2
询问自己的父亲r1
,blabla,直到根r1
。下次当再次询问x
的root时,x
会询问其父亲r1
“我们的根目录是什么?”,r1
没有必要再次重复上一个循环。由于r1
已知其根为r2
,r1
可以直接将其返回x
。
简而言之, x
的root也是x
的父根 。所以我们得到了如何实现 路径压缩 (我认为递归更直接):
int Find(int x)
{
// initial each element's root as itself, which means father[x] = x;
// if an element finds its father is itself, means root is found
if(x == father[x])
return father[x];
int temp = father[x];
// root of x's father is same with root of x's father's root
father[x] = Find(temp);
return father[x];
}
性能非常高,关于路径压缩查找操作的时间复杂度,请参阅:http://www.gabrielnivasch.org/fun/inverse-ackermann