简体   繁体   English

为不相交集实现Find()方法时出现问题

[英]Problem while implementing Find() method for a disjoint set

Been trying to solve this for a while now. 一直在尝试解决这一问题。 I've been given a Node in a Disjoint Set.The Node's implementation is as a class where either it has a different parent node or is it's own 我得到了一个不相交集合中的节点。该节点的实现是一个类,其中它具有不同的父节点或它自己的

class Node {
    Node parent;
    int rank;
    //...constructor and method declarations}

Now, I have to implement the Find method for this class with path compression, called the getParent() method. 现在,我必须使用路径压缩为该类实现Find方法,称为getParent()方法。 I wrote the following code: 我写了以下代码:

Node getParent(){
    while(parent != this)
    {
        parent = parent.getParent();  
    }
    return parent;

I get infinite recursion with this code. 我得到此代码的无限递归。 I know it's problematic, but I do not know how to fix it. 我知道这是有问题的,但我不知道如何解决。 I tried using the this keyword, but it led to the same errors. 我尝试使用this关键字,但导致了相同的错误。 Please help. 请帮忙。 Also, an insight on how to write this code in an iterative manner would be a great plus. 此外,对于如何以迭代方式编写此代码的见解也将是一个不错的选择。 Also, I would like to restructure the tree such that all intermediate nodes between the node on which the getParent() is called and the root have a common parent ie the root node. 另外,我想重构树,以便在调用getParent()的节点与根之间的所有中间节点都具有一个公共父节点,即根节点。

Node getParent() {
    while (parent != this) {
        parent = parent.getParent();  
    }
    return parent;
}

The problems: 问题:

  1. You are mutating the parent field. 您正在更改parent字段。
  2. You should be testing if the parent's parent is itself ... not this. 您应该测试父母的父母本身是否...不是这个。

Your code should probably be: 您的代码可能应该是:

Node getParent() {
    Node p = parent;
    while(p.parent != p) {
        p = p.parent;  
    }
    return p;
}

Or recursively: 或递归地:

Node getParent() {
    return (parent == this) ? this : parent.getParent();
}

(In this case, the iterative version is safer. You should not get "infinite" recursion, but there is still a risk that you may recurse too deep, with a pathologically deep data structure.) (在这种情况下,迭代版本更安全。您不应获得“无限”的递归,但是仍然存在使用病理性深度的数据结构来递归太深的风险。)


UPDATE - apparently, it is your intention that getParent should (incrementally) collapse the parent chain of each Node it visit. 更新 -显然,您的意图是让getParent (逐渐)折叠其访问的每个Node的父链。 In that case, the recursive solution would be: 在这种情况下,递归解决方案将是:

Node getParentAndCollapse() {
    if (parent == this) {
        return this;
    } else {
        parent = parent.getParentAndCollapse();
        return parent;
    }
}

An iterative solution that collapses the entire chain requires two traversals of the chain: 折叠整个链的迭代解决方案需要对链进行两次遍历:

  1. Traverse the chain find the ultimate parent. 遍历链找到最终的父级。
  2. Traverse the chain again, updating all the parent fields to refer to the ultimate parent. 再次遍历链,更新所有parent字段以引用最终父级。
  3. Return the ultimate parent. 返回最终的父母。

Something like this 像这样

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;
}

The first part of your question is already answered by Stephen, and I think this is complete enough. 斯蒂芬已经回答了您的问题的第一部分,我认为这已经足够完整了。

About the second part of your question, I assume you have all the nodes in a list. 关于问题的第二部分,我假设您将所有节点都放在列表中。 So you have List<Node> allNodes . 因此,您具有List<Node> allNodes The needed method to restructure the tree would be: 重组树所需的方法是:

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;
        }
    }
}

The order of this method in the worst case would be O(n^2) and I did not look for a better way, cause you didn't mention the importance of it. 在最坏的情况下,此方法的顺序为O(n^2) ,我没有寻找更好的方法,因为您没有提到它的重要性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM