二进制搜索树在Java中使用递归

时间:2011-03-09 02:49:12

标签: java search recursion binary-tree

我希望有人可以解释我应该如何完成这两种方法。我愿意自己做这项工作而不是懒惰。话虽如此,问题在于:

2种方法:递归需要

  1. 计算二叉树中的节点数,
  2. 计算合适的孩子数量
  3. 我已经实现了以下代码:

    public class IntBSTNode
    {
    
        protected int key;
        protected IntBSTNode left, right;
    
        public IntBSTNode()
        {
            left = right =null;
        }
    
        public IntBSTNode(int el)
        {
            this(el, null, null);
        }
    
        public IntBSTNode( int el, IntBSTNode lt, IntBSTNode rt)
        {
            key = el;
            left =lt;
            right = rt;
        }
    }
    

3 个答案:

答案 0 :(得分:4)

http://en.wikipedia.org/wiki/Recursion

对于递归工作,您需要一个基本案例,以及一组针对基本案例减少的案例和操作。

为了计算二叉树中的节点数,我们可以使用“节点不存在”的基本情况,以及“节点确实存在”的其他情况。

对于另一种情况,(节点确实存在)我们将节点数加1,将每个树的子树(左侧和右侧)中的节点数添加到总计数中。我们如何找到子树中的节点数?只需将我们用于第一个节点的同一组条件应用于子节点。

通过反复分解树的子节点,我们可以获得树中节点的总数

以例如:

     N1
     /\ 
   N2   N3
   /\    \
 N4  N5   N6

让我们调用我们的计数方法countNodes()。

countNodes的伪代码

int countNodes(Node parent):
    if parent:
        return 1 + countNodes(parent.left) + countNodes(parent.right)
    else:
        return 0

countNodes将首先检查您传递给它的节点是否存在。

如果不是(基本情况)返回0 [逻辑上这是有道理的,因为如果节点不存在,那么它的子树中就没有节点不存在]

如果节点存在,则返回1 +子树中节点数的总和。要查找子树中的节点数,我们将在每个子节点上调用countNodes()方法。

在上面的示例树中,我们从N1开始。我们看到N1存在,所以我们现在需要找到的是:

1 + # of nodes in the left subtree + # of nodes in the right subtree.

N1的子树是:

  Left         Right
   N2            N3
   /\             \
 N4  N5            N6

我们首先在N2(N1的左子树)上调用countNodes()方法。

N2存在所以现在我们正在寻找

1 + # of nodes in N2's left subtree + # of nodes in N2's right subtree

N2的子树是:

Left     Right
 N4       N5

在N4上调用countNodes()我们正在寻找

1 + # of nodes in N4's left subtree + # of nodes in N4's right subtree

N4的左侧节点为空,因此当在N4的左侧节点上调用countNodes()时,它将返回0(基本情况)。

N4的右侧节点也为空,因此右侧节点的countNodes()也将返回0

N4的待处理操作可以完成,你有1 + 0 + 0(非基本案例返回值)

现在N2的待处理操作看起来像

1 + 1 + # of nodes right subtree

在N5上调用countNodes()会产生与N4相同的值,因此N2的返回值变为:

1 + 1 + 1

N2返回3到N1的待处理操作,使其看起来像:

1 + 3 + # nodes in right subtree

# nodes in N3 subtree is:
countNodes() on N3 returns 1 + countNodes->null (base) + countNodes()->N6

# nodes in N6 subtree is
countNodes() on N6 returns 1 + countNodes->null (base) + countNodes()->null (base)
return value = 1

# nodes in N3 subtree is 1 + 0 + 1
returns 2

finally the call on N1's countNodes() can complete with 

1 + 3 + 2

countNodes() on N1 returns 6

要计算树中所有正确的节点,您可以使用以下伪代码:

int countRightNodes(Node parent):
    if !parent:
        return 0

    if has right node:
        return 1 + (# of right nodes in left subtree) + (# of right nodes in right subtree)
    else:
        return (# of right nodes in left subtree)

答案 1 :(得分:2)

递归的目的是简化一个复杂的问题直到它是微不足道的,并使用这个小问题的解决方案来找到更复杂问题的解决方案等,直到你可以解决你的实际问题。

在您的情况1)中,复杂的问题是“查找整个树中的节点数”。但我们可以通过说它是numberOfNodesLeftSubtree + numberOfNodesRightSubtree + 1来简化这一点。然后我们可以写:

public int nbNodes(Node root){
    int count = 1 // our actual node
    if(root.left != null){
        count += nbNodes(root.left);
    }
    if(root.right != null){
        count += nbNodes(root.right);
    }

    return count;
}

就这么简单。

答案 2 :(得分:0)

递归思考需要一些练习,但如果做得好,它几乎看起来很神奇。我们需要计算树中的节点数,所以让我们想一想这意味着什么。考虑任何节点及其子树。此子树中的节点数将等于左子树中的节点数加上右子树中的节点数加一(对于所讨论的节点)。因此,如果我们假设我们已经有一个可以计算子树中节点的方法,我们可以对该方法进行两次调用。我们还必须担心基本情况,然后一旦我们有了递归就可以发挥它的魔力。