我已经尝试解决这个问题一段时间了。我在一个Disjoint集合中得到了一个Node。Node的实现是作为一个类,它要么有一个不同的父节点,要么是它自己的
class Node {
Node parent;
int rank;
//...constructor and method declarations}
现在,我必须用路径压缩来实现这个类的Find方法,称为getParent((方法。我写了以下代码:
Node getParent(){
while(parent != this)
{
parent = parent.getParent();
}
return parent;
我用这段代码得到了无限递归。我知道它有问题,但我不知道如何修复它。我尝试使用this
关键字,但它导致了同样的错误。请帮忙。此外,深入了解如何以迭代方式编写此代码将是一大优势。此外,我想重组树,使调用getParent((的节点和根之间的所有中间节点都有一个公共的父节点,即根节点。
Stephen已经回答了您问题的第一部分,我认为这已经足够完整了。
关于你问题的第二部分,我假设你有一个列表中的所有节点。所以你有List<Node> allNodes
。重组树所需的方法是:
public void reStructureTree(List<Node> allNodes){
for(Node item: allNodes){
Node p = item.parent;
List<Node> branch = new ArrayList<>();
while (p.parent != p){
branch.add(p);
p = p.parent;
}
for(Node branchItem : branch){
branchItem.parent = p;
}
}
}
在最坏的情况下,这种方法的顺序是O(n^2)
,我没有寻找更好的方法,因为你没有提到它的重要性
Node getParent() {
while (parent != this) {
parent = parent.getParent();
}
return parent;
}
问题:
- 您正在更改
parent
字段 - 你应该测试父母的父母是否是自己。。。不是这个
您的代码可能应该是:
Node getParent() {
Node p = parent;
while(p.parent != p) {
p = p.parent;
}
return p;
}
或者递归:
Node getParent() {
return (parent == this) ? this : parent.getParent();
}
(在这种情况下,迭代版本更安全。你不应该得到"无限"递归,但仍然有可能递归得太深,具有病态的深层数据结构。(
更新-显然,您的意图是getParent
应该(逐步(折叠它访问的每个Node
的父链。在这种情况下,递归解决方案是:
Node getParentAndCollapse() {
if (parent == this) {
return this;
} else {
parent = parent.getParentAndCollapse();
return parent;
}
}
折叠整个链的迭代解决方案需要链的两个遍历:
- 遍历链,找到最终父级
- 再次遍历链,更新所有
parent
字段以引用最终父级 - 返回最终的父对象
类似的东西
Node getParentAndCollapse() {
Node p = getParent(); // iterative version
Node n = this;
while (n.parent != p) {
Node np = n.parent;
n.parent = p;
n = np;
}
return p;
}