Algorithm 为什么在代码中需要这一行才能从BST中删除?
我正在努力学习更多关于二叉树的知识,我遇到了一个如何找到后续节点的方法(当试图删除节点时),我很难理解其中的一部分。 这是密码Algorithm 为什么在代码中需要这一行才能从BST中删除?,algorithm,data-structures,binary-search-tree,Algorithm,Data Structures,Binary Search Tree,我正在努力学习更多关于二叉树的知识,我遇到了一个如何找到后续节点的方法(当试图删除节点时),我很难理解其中的一部分。 这是密码 private Node getSuccessor(Node delNode){ Node successorParent = delNode; Node successor = delNode; Node current = delNode.rightChild; while(current != null){
private Node getSuccessor(Node delNode){
Node successorParent = delNode;
Node successor = delNode;
Node current = delNode.rightChild;
while(current != null){
successorParent = successor;
successor = current;
current = current.leftChild;
} // end of if
if(successor != delNode.rightChild){
successorParent.leftChild = successor.rightChild;
successor.rightChild = delNode.rightChild;
}
return successor;
}
我完全理解while循环和其中发生的事情。我不明白的是if声明,特别是
successor.rightChild = delNode.rightChild;
为什么要将delNode的正确子节点分配给后续节点的正确子节点?为什么需要if语句?GetSuccession()的作用是查找delNode的后续节点,即最小值大于delNode的节点,即delNode下右子树中最左边的节点。然后将其从右子树中移除,并将右子树附加到后续子树下的右侧
使用条件的原因是,如果后继节点是delNode的正确子节点,则它已经位于正确子树的顶部,并且不需要将其从子树中取出并移动到子树的顶部
在下一步中,将删除delNode,后续节点将附加到delNode的父节点,delNode下的左侧子树将附加到后续节点下的左侧子树。所有这些的效果是用其继任者取代delNote
(此方法不是从二叉树中删除节点的最直接的方法。您可以简单地将右子树附加到delNode的父树,将左子树附加到后续树下的左侧。但此更复杂的方法的优点是不增加树的高度,因为每个节点都保持在相同的深度,或者移动到c彻底失败。)
下面是一个我们要删除节点3的示例:我们发现它的后继节点是4,我们从右子树中删除4并将其放置在子树的顶部,然后我们用后继节点4替换节点3并将左子树附加到它:
9 9
/ \ / \
3 ... 4 4 ...
/ \ \ / \
2 6 6 6 2 6
/ / \ / \ / \ / / \
1 4 7 4 7 5 7 1 5 7
\ \ \ \ \ \
5 8 5 8 8 8
(您会注意到,删除节点后,每个节点的深度都与之前相同,或者已移近根,因此树的高度没有增加。)
现在考虑一个例子,我们将再次删除节点3,但是我们发现它的继承者节点4已经在右子树的顶部,这意味着我们可以立即替换继承者4的节点3并将左子树连接到它,而不必首先将节点4移动到右子树的顶部:
8 8
/ \ / \
3 ... 4 ...
/ \ / \
2 4 4 2 6
/ \ \ / / \
1 6 6 1 5 7
/ \ / \
5 7 5 7
此代码试图解释两种情况。第一种情况是删除一个节点X,该节点的继承者Y是其直接的右子节点:
X
\
Y
\
Z
在本例中,我们最终将用Y替换X,因此该方法可以返回Y并说“这是现在替换X的节点。”
另一方面,假设X的后继Y位于其右子树的子树中:
X
\
A
/ \
Y C
\
B
在这种情况下,我们不能盲目地用Y替换X,因为这样做会丢失节点A和子树C中的所有内容。因此,在我们说“嘿,树-用节点Y替换节点X”之前,我们会重新排列树中的节点,使它们看起来像这样:
X
\
Y
\
A
/ \
B C
现在,当我们用Y替换X时,我们没有丢失树中的任何其他节点
顺便说一句,这里的形状是通过交换X和Y,然后删除X(这是在过去的点Y中)形成的通过使Y的前父级将Y的前右子树作为其左子级。通过这些行,看看您是否可以看到这是如何工作的。自行解决这一问题的最简单方法是运行代码,并观察两者之间的差异。老实说,不必过于仔细地阅读核心,这看起来不像是一个问题ny normal“在二叉树中查找任何内容”实现,因为它会修改树。但是,一个八字树会通过将查询的节点移到树的顶部来修改树,但是问题中的代码也不足以做到这一点。@Carcigenicate这是真的!!我会尝试这么做。@RockySingh老实说,这是你应该尽可能做的第一件事(我不想听起来像是在说这个)。学习(在我看来)最好的方法就是乱搞代码。REPL非常适合这样做。