Java 红黑树-如何找到节点';谁的父母?
在红黑树中,旋转时,需要知道谁是特定节点的父节点。 但是,该节点仅引用右或左子节点 我想给一个节点实例变量“parent”,但正是因为这个原因,我认为这样做不值得,而且每次旋转更改父引用也太复杂了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()方法
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: 通常插入的算法为:
至于这是否比父指针方法更好,这在我看来是有争议的——我倾向于使用父指针方法,因为它简单,不需要维护辅助数据结构或广泛使用递归。也就是说,这两种方法都比在应用重新平衡/着色例程时查询当前节点的父节点要好。我可能错了,但我认为通常的方法是将父节点作为调用堆栈上的参数传递给rotate函数。您应该看看libavl。正确的方法是在搜索时把祖先放在一堆。我不认为这是主观的。如果你想拥有一棵R-B树,那可能是因为你愿意为了追求更快的操作而牺牲一些东西。如果你的内存如此紧张,为什么不使用数组呢?我认为有一些算法可以说,不必维护数据结构的折衷是值得的,因为计算复杂度的微小增加。我个人认为这不是其中之一。我只是想避免给出一个笼统的答案。看起来《永远困惑》已经不在了-(非常遗憾,我从那里学到了很多CS!真是太遗憾了。幸运的是,wayback机器仍然有细节。