Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 红黑树-如何找到节点';谁的父母?_Java_Parent_Red Black Tree - Fatal编程技术网

Java 红黑树-如何找到节点';谁的父母?

Java 红黑树-如何找到节点';谁的父母?,java,parent,red-black-tree,Java,Parent,Red Black Tree,在红黑树中,旋转时,需要知道谁是特定节点的父节点。 但是,该节点仅引用右或左子节点 我想给一个节点实例变量“parent”,但正是因为这个原因,我认为这样做不值得,而且每次旋转更改父引用也太复杂了 public class Node { private left; private right; private isRed; private parent; //I don't think this is good idea } 所以,我的解决方案是编写findParent()方法

在红黑树中,旋转时,需要知道谁是特定节点的父节点。 但是,该节点仅引用右或左子节点

我想给一个节点实例变量“parent”,但正是因为这个原因,我认为这样做不值得,而且每次旋转更改父引用也太复杂了

public class Node {
  private left;
  private right;
  private isRed;
  private parent; //I don't think this is good idea
}
所以,我的解决方案是编写findParent()方法,使用搜索来查找父对象。我想知道是否有其他方法可以找到节点的父节点

我的解决方案:

样本树:

    50
    / \
   25  75
如果要查找节点25的父节点,请传递如下内容:

Node parent = findParent(Node25.value);
它返回node50

protected Node findParent(int val) {
        if(root == null) {
            return null;
        }
        Node current = root;
        Node parent = current;
        while(true) {
            if(current.val == val) { //found
                return parent;
            }
            if(current == null) { //not found
                return null;
            }
            parent = current;
            if(current.val > val) { //go left
                current = current.left;
            }
            else { //go right
                current = current.right; 
            }
        }
    }

存储父对象肯定比查找它要好。更新父引用没有那么复杂

我想给一个节点实例变量“parent”,但正是因为这个原因,我认为不值得这么做

要使节点具有父级引用,每个节点需要一个额外的指针/引用。将此与在需要了解给定节点的父节点时遍历树进行比较

这是两者之间的权衡

  • 维护额外引用以及在修改节点时使其保持最新的成本
  • 必须遍历树才能找到给定节点的父节点的计算成本和复杂性
  • 我认为这两个选项之间的选择有点主观,但就我个人而言,我会选择只跟踪
    父项
    引用


    作为您的参考点,
    java.util.TreeMap
    被实现为一个红黑树,其中
    条目
    节点包含
    ,和
    parent
    引用。

    当您遍历树以到达枢轴节点时,您可以缓存上一个父节点,或者如果需要多个级别的“撤消”,则可以将每个遍历的节点缓存到堆栈上


    此缓存将是旋转算法的局部变量,因此它不需要树中更多的空间或昂贵的额外遍历。

    使用父指针是可选的。如果放弃父指针,则必须使用递归(递归方法调用保留堆栈上的父信息)编写插入/删除操作,或者编写一个迭代版本,在向下移动树时维护自己的父堆栈

    一个非常好的描述红黑树可以在这里找到

    这包括对许多rbtree实现的描述,包括有无父指针

    如果您确实想节省空间(这是很公平的),可以在这里找到关于rbtree实现的非常优秀的描述


    如果insert/delete实现使用您描述的用于搜索节点父节点的方法,则效率将非常低。使用指针或递归。

    除了父指针和再次查询父指针之外,另一种解决方案是维护祖先堆栈

    假设有人希望在以下树中插入23:

    通常插入的算法为:

  • 查找23所在的节点(如果它在树中)

  • 如果23已经存在,返回失败

  • 如果23还没有,就放在那里

  • 根据需要运行重新平衡/着色例程

  • 现在,要使用堆栈方法,您需要分配一个足够大的堆栈,以支持树的每一层有一个节点(我认为2*天花(Log2(count))+2)应该包括在内。您甚至可以保留为插入或删除分配的堆栈,并在开始插入时将其清除

    所以,看看根。将其推到堆栈上。23大于根中的值,所以向右走。现在将节点当前节点(值21)推到堆栈上。如果树中有23,则它必须位于当前节点的右侧。但当前节点右侧的节点是空哨兵。因此,应该用具有您的值的节点替换空哨兵。父对象是堆栈顶部的项目(最近推送的),祖父母是下一个队列。。。等等,既然你似乎在学习。。。Java为您提供了一个堆栈接口,所以您不需要开发自己的堆栈来实现这一点。就用他们的吧


    至于这是否比父指针方法更好,这在我看来是有争议的——我倾向于使用父指针方法,因为它简单,不需要维护辅助数据结构或广泛使用递归。也就是说,这两种方法都比在应用重新平衡/着色例程时查询当前节点的父节点要好。

    我可能错了,但我认为通常的方法是将父节点作为调用堆栈上的参数传递给rotate函数。您应该看看libavl。正确的方法是在搜索时把祖先放在一堆。我不认为这是主观的。如果你想拥有一棵R-B树,那可能是因为你愿意为了追求更快的操作而牺牲一些东西。如果你的内存如此紧张,为什么不使用数组呢?我认为有一些算法可以说,不必维护数据结构的折衷是值得的,因为计算复杂度的微小增加。我个人认为这不是其中之一。我只是想避免给出一个笼统的答案。看起来《永远困惑》已经不在了-(非常遗憾,我从那里学到了很多CS!真是太遗憾了。幸运的是,wayback机器仍然有细节。