将迭代函数转换为递归函数

时间:2014-02-28 07:45:03

标签: recursion binary-search-tree

我在编程中发现的最难的概念之一就是递归。我一直试图将此函数转换为递归调用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(在评论中)真的让我大脑破碎。

2 个答案:

答案 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()的递归部分是搜索要删除的节点。一旦找到,合并树的算法就不会改变。