我在编程中发现的最难的概念之一就是递归。我一直试图将此函数转换为递归调用2天,但我无法让它工作。它是BST的删除功能
public void deleteByMerging(T el) {
BSTNode<T> tmp, node, p = root, prev = null;
while (p != null && !p.el.equals(el)) { // find the node p
prev = p; // with element el;
if (el.compareTo(p.el) < 0)
p = p.right;
else p = p.left;
}
node = p;
if (p != null && p.el.equals(el)) {
if (node.right == null) // node has no right child: its left
node = node.left; // child (if any) is attached to its parent;
else if (node.left == null) // node has no left child: its right
node = node.right; // child is attached to its parent;
else { // be ready for merging subtrees;
tmp = node.left; // 1. move left
while (tmp.right != null) // 2. and then right as far as
tmp = tmp.right; // possible;
tmp.right = // 3. establish the link between
node.right; // the rightmost node of the left
// subtree and the right subtree;
node = node.left; // 4.
}
if (p == root)
root = node;
else if (prev.left == p)
prev.left = node;
else prev.right = node; // 5.
}
else if (root != null)
System.out.println("el " + el + " is not in the tree");
else System.out.println("the tree is empty");
}
我找到了这个节点,但是步骤1到5(在评论中)真的让我大脑破碎。
答案 0 :(得分:0)
首先,您需要“找到”该节点。让我们尝试以递归的方式思考:
function find(el, p)
if p == null, not found! (return p, i.e. null)
if p.el == el, found! (return p)
if el < p.el, return find(el, p.right)
if el > p.el, return find(el, p.left)
这是递归的,对吧?因此,BSTNode<T> node = find(el, root)
将返回与el匹配的节点或返回null,这意味着NOT FOUND。
合并剩余的删除只管理对象引用,所以我不评论。
答案 1 :(得分:0)
我认为合并算法步骤3和4存在一些问题。想象一下,您正在删除具有左右子树的节点。空白空间将替换为必须满足BST条件的节点(即,大于左节点且小于右节点)。该替换节点位于最右边的子树中(注释的第2步)。 tmp指向该节点。所以现在我们有“node”指向被删除的节点,“tmp”指向替换节点。在步骤3中,这是链接发生的地方。
tmp.right = node.right
tmp.left = node.left // missing from the algorithm
现在在步骤4中,这是“节点”变量被改变为指向替换节点“tmp”的地方,因此在步骤5中,前一节点“prev”可以链接到替换节点。我相信第4步应该是
node = tmp;
而不是
node = node.left;
请检查我的分析是否正确。也许这就是为什么你无法理解发生了什么。 deleteByMerging()的递归部分是搜索要删除的节点。一旦找到,合并树的算法就不会改变。