在二进制搜索树中查找高度

时间:2010-04-08 04:47:37

标签: binary-tree

我想知道是否有人可以帮我修改这个方法来找到二叉搜索树的高度。到目前为止,我的代码看起来像这样。但是,我得到的答案比实际高度大1.然而当我从我的返回语句中删除+1时,它比实际高度小1.我仍然试图用我的头围绕递归这些BST。任何帮助将不胜感激。

public int findHeight(){
    if(this.isEmpty()){
        return 0;
    }
    else{
        TreeNode<T> node = root;
        return findHeight(node);
    }
}
private int findHeight(TreeNode<T> aNode){
    int heightLeft = 0;
    int heightRight = 0;
    if(aNode.left!=null)
        heightLeft = findHeight(aNode.left);
    if(aNode.right!=null)
        heightRight = findHeight(aNode.right);
    if(heightLeft > heightRight){
        return heightLeft+1;
    }
    else{
        return heightRight+1;
    }
}

24 个答案:

答案 0 :(得分:101)

问题出在你的基础案例中。

“树的高度是树中从根到最深节点的路径长度。只有一个节点(根)的(带根)树的高度为零。” - Wikipedia

如果没有节点,则要返回-1而不是0.这是因为您最后添加了1。

因此,如果没有节点,则返回-1,取消+1。

int findHeight(TreeNode<T> aNode) {
    if (aNode == null) {
        return -1;
    }

    int lefth = findHeight(aNode.left);
    int righth = findHeight(aNode.right);

    if (lefth > righth) {
        return lefth + 1;
    } else {
        return righth + 1;
    }
}

答案 1 :(得分:32)

二叉搜索树的高度等于number of layers - 1

请参阅http://en.wikipedia.org/wiki/Binary_tree

上的图表

你的递归是好的,所以只需在根级别减去一个。

另请注意,您可以通过处理空节点来清理函数:

int findHeight(node) {
  if (node == null) return 0;
  return 1 + max(findHeight(node.left), findHeight(node.right));
}

答案 2 :(得分:19)

int getHeight(Node node) {
 if (node == null) return -1;

 return 1 + Math.max(getHeight(node.left), getHeight(node.right));
}

答案 3 :(得分:8)

IMO,您的代码将受益于简化。当子指针为空时,不要尝试结束递归,而只在当前指针为空时结束递归。这使得代码 lot 更易于编写。在伪代码中,它看起来像这样:

if (node = null)
    return 0;
else
    left = height(node->left);
    right = height(node->right);
    return 1 + max(left, right);

答案 4 :(得分:4)

这是未经测试的,但显然是正确的:

private int findHeight(Treenode aNode) {
  if (aNode.left == null && aNode.right == null) {
    return 0; // was 1; apparently a node with no children has a height of 0.
  } else if (aNode.left == null) {
    return 1 + findHeight(aNode.right);
  } else if (aNode.right == null) {
    return 1 + findHeight(aNode.left);
  } else {
    return 1 + max(findHeight(aNode.left), findHeight(aNode.right));
  }
}

通常简化代码比找出它的原因更容易。这段代码很容易理解:四种可能的情况以明显正确的方式清楚地处理:

  • 如果左侧树和右侧树均为空,则返回1,因为根据定义,单个节点的高度为1。
  • 如果左侧或右侧树(但不是两个!)都为空,则返回非空树的高度,加上1以说明当前节点的添加高度。
  • 如果两个树都不为null,则返回较高子树的高度,再加上当前节点的一个。

答案 5 :(得分:4)

像我这样喜欢一线解决方案的人:

public int getHeight(Node root) {
    return Math.max(root.left != null ? getHeight(root.left) : -1, 
                    root.right != null ? getHeight(root.right) : -1) 
                    + 1;
}

答案 6 :(得分:4)

class Solution{
    public static int getHeight(Node root) {
        int height = -1;

        if (root == null) {
            return height;
        } else {
            height = 1 + Math.max(getHeight(root.left), getHeight(root.right));
        }

        return height;
    }

答案 7 :(得分:3)

    public void HeightRecursive()
    {
        Console.WriteLine( HeightHelper(root) ); 
    }

    private int HeightHelper(TreeNode node)
    {
        if (node == null)
        {
            return -1;
        }
        else
        {
            return 1 + Math.Max(HeightHelper(node.LeftNode),HeightHelper(node.RightNode));           
        }
    }

C#代码。 在BST类中包含这两种方法。你需要两种方法来计算树的高度。 HeightHelper计算它,&amp; HeightRecursive在main()中打印它。

答案 8 :(得分:3)

这是一种简洁而有希望的表达方式:

  private int findHeight(TreeNode<T> aNode){
    if(aNode == null || (aNode.left == null && aNode.right == null))
      return 0;
    return Math.max(findHeight(aNode.left), findHeight(aNode.right)) + 1;
  }

如果当前节点为null,则没有树。如果两个孩子都是,那么就有一层,这意味着0高。这使用高度的定义(由Stephen提到)作为层数 - 1

答案 9 :(得分:2)

我知道我迟到了。在研究了此处提供的精彩答案之后,我认为我的帖子将为该帖子增加一些价值。尽管发布的答案令人惊讶且易于理解,但是所有人都在线性时间内计算BST的高度。我认为这可以改进,并且可以在恒定时间内检索到Height,因此请写出此答案–希望您会喜欢。 让我们从 Node 类开始:

public class Node
{
    public Node(string key)
    {
        Key = key;
        Height = 1;
    }    

    public int Height { get; set; } 
    public string Key { get; set; }
    public Node Left { get; set; }
    public Node Right { get; set; }

    public override string ToString()
    {
        return $"{Key}";
    }
}

BinarySearchTree

因此,您可能在这里已经猜到了窍门……我保持节点实例变量Height来跟踪添加时的每个节点。 让我们转到BinarySearchTree类,该类允许我们向BST中添加节点:

public class BinarySearchTree
{
    public Node RootNode { get; private set; }

    public void Put(string key)
    {
        if (ContainsKey(key))
        {
            return;
        }

        RootNode = Put(RootNode, key);
    }

    private Node Put(Node node, string key)
    {
        if (node == null) return new Node(key);

        if (node.Key.CompareTo(key) < 0)
        {
            node.Right = Put(node.Right, key);
        }
        else
        {
            node.Left = Put(node.Left, key);
        }       
        
        // since each node has height property that is maintained through this Put method that creates the binary search tree.
        // calculate the height of this node by getting the max height of its left or right subtree and adding 1 to it.        
        node.Height = Math.Max(GetHeight(node.Left), GetHeight(node.Right)) + 1;
        return node;
    }

    private int GetHeight(Node node)
    {
        return node?.Height ?? 0;
    }

    public Node Get(Node node, string key)
    {
        if (node == null) return null;
        if (node.Key == key) return node;

        if (node.Key.CompareTo(key) < 0)
        {
            // node.Key = M, key = P which results in -1
            return Get(node.Right, key);
        }

        return Get(node.Left, key);
    }

    public bool ContainsKey(string key)
    {
        Node node = Get(RootNode, key);
        return node != null;
    }
}

一旦在BST中添加了键,值,我们就可以调用RootNode对象的Height属性,该属性将在恒定时间内向我们返回RootNode树的高度。 技巧是在将新节点添加到树中时保持高度更新。 希望这对狂热的计算机科学爱好者有所帮助!

单元测试:

[TestCase("SEARCHEXAMPLE", 6)]
[TestCase("SEBAQRCHGEXAMPLE", 6)]
[TestCase("STUVWXYZEBAQRCHGEXAMPLE", 8)]
public void HeightTest(string data, int expectedHeight)
{
    // Arrange.
    var runner = GetRootNode(data);

    
    //  Assert.
    Assert.AreEqual(expectedHeight, runner.RootNode.Height);
}

private BinarySearchTree GetRootNode(string data)
{
    var runner = new BinarySearchTree();
    foreach (char nextKey in data)
    {
        runner.Put(nextKey.ToString());
    }

    return runner;
}

注意:这种在每次“放置”操作中保持树高的想法是受Algorithm (Fourth Edition)书第3章(第399页)中“ BST大小”方法的启发。

答案 10 :(得分:2)

int height(Node* root) {
        if(root==NULL) return -1;
        return max(height(root->left),height(root->right))+1;
}

从左子树和右子树中获取最大高度并将其加1,这也可以处理基本情况(具有1个节点的树的高度为0)。

答案 11 :(得分:2)

public int height(){

    if(this.root== null) return 0;

    int leftDepth = nodeDepth(this.root.left, 1);
    int rightDepth = nodeDepth(this.root.right, 1);

    int height = leftDepth > rightDepth? leftDepth: rightDepth;

    return height;
}


private int nodeDepth(Node node, int startValue){

    int nodeDepth = 0;

    if(node.left == null && node.right == null) return startValue;
    else{
        startValue++;
        if(node.left!= null){
            nodeDepth = nodeDepth(node.left, startValue);
        }

        if(node.right!= null){
            nodeDepth = nodeDepth(node.right, startValue);
        }
    }

    return nodeDepth;
}

答案 12 :(得分:2)

上面给出的高度定义不正确。这就是深度的定义。

“树中节点 M 的深度是从树根到 M 的路径长度。树的高度是一个树中最深节点的深度。所有深度 d 的节点都在树中的 d 级别。根是0级唯一的节点,它的深度为0.“

引文:“数据结构和算法分析的实用介绍” 3.2版(Java版) Clifford A. Shaffer 计算机科学系 Virginia Tech 布莱克斯堡,弗吉尼亚州24061

答案 13 :(得分:1)

将tempHeight设置为静态变量(最初为0)。

static void findHeight(Node node,int count){

    if (node == null) {
        return;
    }
    if ((node.right == null) && (node.left == null)) {
        if (tempHeight < count) {
            tempHeight = count;

        }

    }

    findHeight(node.left, ++count);
    count--; //reduce the height while traversing to a different branch
    findHeight(node.right, ++count);

}

答案 14 :(得分:1)

这是Java中的解决方案有点冗长但有效..

public static int getHeight (Node root){
    int lheight = 0, rheight = 0;
    if(root==null) {
        return 0;
    }
    else {
        if(root.left != null) {
            lheight = 1 + getHeight(root.left);
            System.out.println("lheight" + " " + lheight);
        }
        if (root.right != null) {
            rheight = 1+ getHeight(root.right);
            System.out.println("rheight" + " " + rheight);
        }
        if(root != null && root.left == null && root.right == null) {
            lheight += 1; 
            rheight += 1;
        }

    }
    return Math.max(lheight, rheight);
    }

答案 15 :(得分:1)

这是C#

中的解决方案
    private static int heightOfTree(Node root)
    {
        if (root == null)
        {
            return 0;
        }

        int left = 1 + heightOfTree(root.left);
        int right = 1 + heightOfTree(root.right);

        return Math.Max(left, right);
    }

答案 16 :(得分:1)

 int getHeight(Node* root)
 {
   if(root == NULL) return -1;
   else             return max(getHeight(root->left), getHeight(root->right)) + 1;
 }

答案 17 :(得分:1)

public int getHeight(Node node)
{
    if(node == null)
        return 0;

    int left_val = getHeight(node.left);
    int right_val = getHeight(node.right);
    if(left_val > right_val)
        return left_val+1;
    else
        return right_val+1;
}

答案 18 :(得分:1)

我猜这个问题可能意味着两件事......

  1. 高度是最长分支中的节点数: -

    int calcHeight(node* root){ if(root==NULL) return 0; int l=calcHeight(root->left); int r=calcHeight(root->right); if(l>r) return l+1; else return r+1; }

  2. 高度是树中的节点总数本身:

    int calcSize(node* root){ if(root==NULL) return 0; return(calcSize(root->left)+1+calcSize(root->right)); }

答案 19 :(得分:1)

//查找BST高度的函数

int height(Node* root) {
    if(root == NULL){
        return -1;
    }

    int sum=0;
    int rheight = height(root->right);
    int lheight = height(root->left);

    if(lheight>rheight){
        sum = lheight +1;
    }
    if(rheight > lheight){
        sum = rheight + 1;
    }

    return sum;
}

答案 20 :(得分:0)

对于任何读这篇文章的人来说!!!!

HEIGHT定义为从根节点到叶节点的最长路径中的节点数。因此:只有根节点的树的高度为1而不是0。

给定节点的LEVEL是距离根加1的距离。因此:根位于1级,其子节点位于2级,依此类推。

(信息由Data Structures:Abstraction and Design Using Java提供,第2版,作者:Elliot B. Koffman&amp; Paul A. T. Wolfgang) - 用于数据结构课程的书我目前正在哥伦布州立大学学习。

答案 21 :(得分:0)

enter image description here

根据Thomas H. Cormen,Charles E. Leiserson,Ronald L.Rivest和Clifford Stein的“算法简介”,以下是树高的定义:

  

节点中节点的高度   树是从节点到节点的最长简单向下路径上的边数   一片叶子,一棵树的高度就是其根的高度。一棵树的高度也是   等于树中任何节点的最大深度。

以下是我的红宝石解决方案。大多数人在实现过程中忘记了空树或单节点树的高度。

def height(node, current_height)
  return current_height if node.nil? || (node.left.nil? && node.right.nil?)
  return [height(node.left, current_height + 1), height(node.right, current_height + 1)].max if node.left && node.right
  return height(node.left, current_height + 1) if node.left
  return height(node.right, current_height + 1)
end

答案 22 :(得分:0)

int maxDepth(BinaryTreeNode root) {
    if(root == null || (root.left == null && root.right == null)) {
       return 0;
    }

    return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}

答案 23 :(得分:0)

二叉树的高度

public static int height(Node root)
    {
        // Base case: empty tree has height 0
        if (root == null) {
            return 0;
        }

        // recursively for left and right subtree and consider maximum depth
        return 1 + Math.max(height(root.left), height(root.right));
    }