Java Recursivley测试二叉搜索树是否完整

Java Recursivley测试二叉搜索树是否完整,java,recursion,binary-search-tree,Java,Recursion,Binary Search Tree,几天前,我问了一个关于同一个项目的问题,从那时起,我们的团队已经完成了我们所有的方法,除了一个用于确定二叉搜索树是否完成的方法 我们使用一个包装器方法和一个助手方法来递归地实现这一点 我们知道我们需要检查到树的h-1级(h是高度)以确保它是完美的,然后我们需要确保最后一级上的所有叶节点都从左到右没有间隙 无论我们尝试什么,我们都无法弄清楚如何递归地检查剩余的叶节点,以确保它们从左到右是连续的。我们能够确保它是完美的水平(h-1)然而 有人能告诉我们如何递归检查最后一级的叶节点以确保它们是左对齐的

几天前,我问了一个关于同一个项目的问题,从那时起,我们的团队已经完成了我们所有的方法,除了一个用于确定二叉搜索树是否完成的方法

我们使用一个包装器方法和一个助手方法来递归地实现这一点

我们知道我们需要检查到树的h-1级(h是高度)以确保它是完美的,然后我们需要确保最后一级上的所有叶节点都从左到右没有间隙

无论我们尝试什么,我们都无法弄清楚如何递归地检查剩余的叶节点,以确保它们从左到右是连续的。我们能够确保它是完美的水平(h-1)然而

有人能告诉我们如何递归检查最后一级的叶节点以确保它们是左对齐的吗

到目前为止,这是代码吗

public boolean isComplete() 
{
    if (isPerfect(root))
        return true;    
    return isComplete(root);

}
/**
 * 
 * @param node
 * @return 
 */
private boolean isComplete(Node node)
{  
   if (height(node) > 1)
   {
   if (node.left != null && node.right != null && (height(node.left) == height(node.right)))
       return isComplete(node.left) && isComplete(node.right);
   else
       return false;
   }

}

p.S由于每个完美树都是完整的,所以所有琐碎的情况都是通过isPerfect()方法来处理的

我将尝试首先记录算法以检查完整性,然后继续代码

让我们用预顺序遍历方法来考虑这一点

  • 需要树中的节点数
  • 从根递归,将根视为节点索引0
  • 若节点为空,则表示树已完成
  • 如果节点索引大于(或等于)树中的节点数,则该索引不完整
  • 在左、右子树上递归;给定预顺序遍历方法,左树得到索引
    2*i+1
    ,右树得到
    2*i+2
对为什么这应该起作用有一点理解

下面是一个完整的树[方括号中包含节点索引]注意,此完整二叉树的节点索引严格小于完整二叉树中的节点数

          1 [0]
         / \
        /   \
   [1] 2     3 [2]
      / \
     /   \
[3] 4     5 [4]
返回树中节点总数的函数

private int totalNodes(Node root) {
    if (root == null) 
        return 0;

    return 1 + totalNodes(root.left) + totalNodes(root.right));
}
现在,包装器isComplete()函数[具有0个参数,因为根将是一个类字段]

public boolean isComplete() {
    return isCompleteHelper(root, 0, totalNodes(root));
}
isCompleteHelper()文件


我可以和我的教授交流,他告诉mof一个O(n)方法,与这里给出的一些答案相比,在isComplete方法中,只使用一个参数

这个答案是我最初问题的最佳答案

  • 如果hR>hL,则树不完整
  • 如果hL-HR>1,则树不完整
  • 如果hR==hL,则左子树必须是完美的,右子树必须是完整的
  • 否则(hL-hR==1),则左 子树必须是完美的,并且是正确的子树 必须是完美的

  • 步骤3和4必须递归地检查树isPerfect()和isComplete()

    我是否还没有测试、运行或编译它。因此,请小心一些小错误。虽然代码可能正常工作,但它偏离了在包装器方法中只使用一个参数的要求。谢谢你的意见!我可能可以使用您提供的步骤来变戏法。@sbowde4我不知道您是否注意到,包装器只使用一个参数包装器方法不应该使用参数,而助手应该是我的意思。仅显示一个节点参数allowed@sbowde4嗯,是的。我做了编辑。由于,
    root
    是一个类字段,
    isComplete()
    wrapper显然不需要它作为参数。根据这种方法,助手需要3个参数,这是无法更改的。否则,您可以使用高度来测试完整性,这也是非常基本的。
    private booelan isCompleteHelper(Node root, int indx, int totalNodes) {
    
        // empty tree 
        if (root == null)        
           return true;
    
        // present index >= number of nodes in tree
        if (indx >= totalNodes)
           return false;
    
        // recurse
        return isCompleteHelper(root.left, 2*indx+1, totalNodes) && isCompleteHelper(root.right, 2*indx+2, totalNodes);
    }