暂时尝试解决此问题。我得到了一个不相交集合中的节点。该节点的实现是一个类,在该类中它具有不同的父节点或者是它自己的
class Node {
Node parent;
int rank;
//...constructor and method declarations}
现在,我必须使用路径压缩为该类实现Find方法,称为getParent()方法。我写了以下代码:
Node getParent(){
while(parent != this)
{
parent = parent.getParent();
}
return parent;
我得到了这个代码的无限递归。我知道这是有问题的,但我不知道如何解决。我尝试使用this
关键字,但导致了相同的错误。
请帮忙。此外,对于如何以迭代方式编写此代码的见解也将是一个不错的选择。
另外,我想重新构造树,以便在调用getParent()的节点与根之间的所有中间节点都具有一个公共父节点,即根节点。
答案 0 :(得分:0)
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;
}
答案 1 :(得分:0)
斯蒂芬已经回答了问题的第一部分,我认为这已经足够完整了。
关于问题的第二部分,我假设您将所有节点都放在列表中。因此,您拥有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)
,并且我没有寻找更好的方法,因为您没有提到它的重要性。