我试图了解有关二叉树的更多信息,并且我遇到了一个关于如何找到后继节点的方法(当尝试删除节点时),我很难理解其中的一部分。 这是代码。
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语句是必要的?
答案 0 :(得分:1)
getSuccessor()所做的是找到delNode的后继者,delNode是具有大于delNode的最小值的节点,即delNode下右子树中最左边的节点。然后它将其从右侧子树中删除,并将右侧子树附加到后继项下的右侧。
条件的原因是如果后继者是delNode的右子,它已经位于右子树的顶部,并且不需要从子树中取出并移动到顶部它。
在下一步中,delNode将被删除,后继将附加到delNode的父级,delNode下的左子树将附加到后继的左侧。所有这一切的效果是将delNote替换为其继任者。
(此方法不是从二叉树中删除节点的最简单方法。您可以简单地将右子树附加到delNode的父节点,将左子节点附加到左侧的后续节点。但这种更复杂的方法具有不增加树高度的优点,因为每个节点都保持在相同的深度,或者移动到更靠近根的位置。)
这是一个我们要删除节点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
答案 1 :(得分:1)
此代码试图考虑两种情况。第一个是你要删除其继承者Y是其直接右子的节点X:
X
\
Y
\
Z
在这种情况下,我们最终将用Y替换X,因此该方法可以返回Y并说出&#34;这里是现在替换X的节点。&#34; < / p>
另一方面,假设X的后继Y位于其右子树的子树中:
X
\
A
/ \
Y C
\
B
在这种情况下,我们不能盲目地用Y替换X,因为这样做会丢失节点A和子树C中的所有内容。所以在我们说&#34; hey tree之前 - 用节点替换节点X Y,&#34;我们重新排列树中的节点,使它们看起来像这样:
X
\
Y
\
A
/ \
B C
现在,当我们用Y替换X时,我们还没有丢失树中的任何其他节点。
顺便说一下,这里的形状是通过交换X和Y形成的,然后通过让Y的前任父母拥有Y的前者来删除X(在Y中曾经存在的地方)右子树为其左子。跟踪这些行,看看你是否能看到它是如何工作的。