递归:是否需要跟踪和更新传递给函数的变量?

时间:2017-07-27 12:57:59

标签: java recursion

我正在浏览从二叉搜索树中删除节点的代码,我有点困惑

Node deleteRec(Node root, int key)
    {
        /* Base Case: If the tree is empty */
        if (root == null)  return root;

        /* Otherwise, recur down the tree */
        if (key < root.key)
            root.left = deleteRec(root.left, key);
        else if (key > root.key)
            root.right = deleteRec(root.right, key);

        // if key is same as root's key, then This is the node
        // to be deleted
        else
        {
            // node with only one child or no child
            if (root.left == null)
                return root.right;
            else if (root.right == null)
                return root.left;

            // node with two children: Get the inorder successor (smallest
            // in the right subtree)
            root.key = minValue(root.right);

            // Delete the inorder successor
            root.right = deleteRec(root.right, root.key);
        }

        return root;
    }

为什么我们需要在几个地方的root.leftroot.right变量中存储函数调用的结果?由于root的值,即引用被传递给函数,后续调用中的任何更改都将自动更新树,不是吗?那么为什么要将值存储在变量中呢?为了明确我的观点,下面是另一段代码

// A recursive function used by topologicalSort
void topologicalSortUtil(int v, boolean visited[],
                         Stack stack)
{
    // Mark the current node as visited.
    visited[v] = true;
    Integer i;

    // Recur for all the vertices adjacent to this
    // vertex
    Iterator<Integer> it = adj[v].iterator();
    while (it.hasNext())
    {
        i = it.next();
        if (!visited[i])
            topologicalSortUtil(i, visited, stack);
    }

    // Push current vertex to stack which stores result
    stack.push(new Integer(v));
}

这里堆栈正在传递给函数,我们只是在进一步的函数调用中一次又一次地使用它,因为我们知道堆栈将继续在调用之间进行更新。

我错过了什么或者我理解错了什么?有人可以帮我理解。谢谢!!

4 个答案:

答案 0 :(得分:1)

不同递归级别的root对象不是同一个对象。

当您向下递归树时,请使用deleteRecroot.left作为第一个参数调用root.right。因此,下一级递归会将左子树或右子树的根视为其“根”。

这与为stack的第三个参数传递的topologicalSortUtil变量不同:此变量始终保持不变,因此所有级别都可以访问相同的对象。

答案 1 :(得分:1)

删除节点时,必须拉出其下的树部分。否则,您将删除该节点及其所有后代,这是不正确的。

答案 2 :(得分:1)

删除树的节点时,可能需要更新父节点的左或右指针。最简单的情况是当删除的not不是叶子时:在这种情况下,指向它的链接必须设置为null。

如果另外,删除的节点恰好是根节点,则必须更新指向根的指针。

当您调用deleteRec方法时,您无法事先知道返回的值是否与第一个参数相同。

答案 3 :(得分:1)

您的deleteRec方法会收到二叉树的Node并修改树。但是,每个递归调用都会传递给树的不同Node。这与您的第二个示例不同,后者会向每个递归调用传递相同的Stack

现在,当deleteRec找到它应该从树中删除的Node时(当前递归调用的rootNode时应该是Node已删除),它无法从树中删除Node。它必须修改已删除的Node的父Node,才能从树中删除Node。这就是递归调用返回时会发生什么,并且该调用返回的root.left被分配给root.rightread_excel