74

我想知道是否有人可以帮助我修改这个方法来找到二叉搜索树的高度。到目前为止,我的代码看起来像这样。但是,我得到的答案比实际高度大 1。但是当我从 return 语句中删除 +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;
    }
}
4

26 回答 26

142

问题在于您的基本情况。

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

如果没有节点,则要返回 -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;
    }
}
于 2010-04-08T05:26:01.487 回答
38

二叉搜索树的高度等于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));
}
于 2010-04-08T05:08:46.390 回答
27
int getHeight(Node node) {
 if (node == null) return -1;

 return 1 + Math.max(getHeight(node.left), getHeight(node.right));
}
于 2014-09-25T05:20:38.233 回答
11

在我看来,您的代码将受益于简化一点。与其尝试在子指针为空时结束递归,不如仅在当前指针为空时结束递归。这使得代码更容易编写。在伪代码中,它看起来像这样:

if (node = null)
    return 0;
else
    left = height(node->left);
    right = height(node->right);
    return 1 + max(left, right);
于 2010-04-08T05:06:20.590 回答
5
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;
    }
于 2016-07-13T12:13:30.580 回答
5

对于像我这样喜欢单线解决方案的人:

public int getHeight(Node root) {
    return Math.max(root.left != null ? getHeight(root.left) : -1, 
                    root.right != null ? getHeight(root.right) : -1) 
                    + 1;
}
于 2017-03-26T05:37:18.073 回答
4

这是一种简洁且希望正确的表达方式:

  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;
  }

如果当前节点为空,则没有树。如果两个孩子都是,则只有一层,这意味着高度为 0。这使用高度的定义(斯蒂芬提到)作为层数 - 1

于 2010-04-08T04:51:06.660 回答
4

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

private int findHeight(Treenode<T> 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));
  }
}

通常简化你的代码比弄清楚它为什么会出错更容易。这段代码很容易理解:四种可能的情况都以明显正确的方式进行了清晰的处理:

  • 如果左右树都为空,则返回 0,因为根据定义,单个节点的高度为 0。(为 1)
  • 如果左树或右树(但不是两者!)为空,则返回非空树的高度,加上 1 以说明当前节点的添加高度。
  • 如果两棵树都不为空,则返回较高子树的高度,再为当前节点加一。
于 2010-04-08T05:15:53.350 回答
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 计算它,& HeightRecursive 在 main() 中打印它。

于 2011-12-05T11:50:42.040 回答
2

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

“树中节点M的深度是从树根到M的路径长度。树的高度比树中最深节点的深度大一。深度为d的所有节点都是在树的第d层。根是第 0 层的唯一节点,其深度为 0。

引用:“A Practical Introduction to Data Structures and Algorithm Analysis”3.2 版(Java 版)Clifford A. Shaffer 计算机科学系 Virginia Tech Blacksburg, VA 24061

于 2013-05-09T01:31:16.080 回答
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;
}
于 2016-12-31T01:59:40.983 回答
2

//查找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;
}
于 2017-10-15T21:25:28.507 回答
2
int height(Node* root) {
        if(root==NULL) return -1;
        return max(height(root->left),height(root->right))+1;
}

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

于 2018-08-19T05:02:44.743 回答
2

我知道我参加晚会迟到了。在查看了此处提供的精彩答案后,我认为我的答案会为这篇文章增加一些价值。尽管发布的答案令人惊叹且易于理解,但所有答案都是在线性时间内计算到 BST 的高度。我认为这可以改进,并且可以在恒定时间内检索高度,因此写下这个答案 - 希望你会喜欢它。让我们从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;
}

注意:在每个 Put 操作中保持树的高度的想法受到算法(第四版)书第 3 章(第 399 页)中的 BST 大小方法的启发。

于 2020-09-06T00:02:28.993 回答
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)); }

于 2014-02-25T16:14:30.933 回答
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;
}
于 2014-03-13T10:54:12.293 回答
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);
    }
于 2014-04-07T00:44:23.473 回答
1

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

静态无效findHeight(节点节点,整数){

    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);

}
于 2015-05-10T12:31:48.663 回答
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);
    }
于 2016-01-24T17:45:37.263 回答
1
 int getHeight(Node* root)
 {
   if(root == NULL) return -1;
   else             return max(getHeight(root->left), getHeight(root->right)) + 1;
 }
于 2016-11-23T19:14:46.847 回答
0

对于其他阅读此内容的人!!!!

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

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

(信息由 Data Structures: Abstraction and Design Using Java, 2nd Edition,Elliot B. Koffman 和 Paul AT Wolfgang 提供)- 我目前在哥伦布州立大学学习的数据结构课程中使用的书。

于 2013-11-11T22:32:21.933 回答
0

在此处输入图像描述

根据 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
于 2019-04-20T17:43:03.847 回答
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));
}
于 2019-05-05T08:08:19.487 回答
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));
    }
于 2020-06-29T04:23:37.600 回答
0

我自己也在为此苦苦挣扎,试图找到一些优雅的东西,但仍然会产生正确的价值。这是我使用 Swift 的想法。请注意,这height是一个计算变量,在技术上不是一个函数。

class Node<T: Comparable>: NSObject
{
    var left: Node<T>? = nil
    var right: Node<T>? = nil
 
    var isLeaf: Bool { left == nil && right == nil }

    var height: Int {
        if isLeaf { return 0 }
        return 1 + max(left?.height ?? 0, right?.height ?? 0)
    }
}

此 Node 定义还有更多内容,但您可以看到leftandright变量(可能为 nil)和一个isLeafvar ,即true当两者时leftand rightare nil。可能不是最有效的,但我相信它会产生正确的结果。

BST 定义还有一个计算height变量,当树为空时返回 -1。

class BST<T: Comparable>: NSObject
{
    var root: Node<T>?
    var height: Int { root != nil ? root!.height : -1 }
}
于 2022-01-05T01:36:30.917 回答
0
HackerRank Day 22: Finding height in Binary Search Tree, in C#.

     static int getHeight(Node root)
        {
            //Write your code here
            int countr = 0,countl=0;
            Node Leftsubtree=root.left;
            Node rightsubtree = root.right;
            int data=root.data;
             if(root==null ||(root.left == null && root.right == null))
            {
                return 0;
            }
             else
            {
                while (Leftsubtree != null)
                {
                        if(Leftsubtree.data<data)
                        {
                        Leftsubtree = Leftsubtree.left==null?Leftsubtree.right:Leftsubtree.left;
                        countl++;
                        }
                }
                while (rightsubtree != null)
                {
                    if (rightsubtree.data > data)
                    {
                        rightsubtree = rightsubtree.right == null ? rightsubtree.left : rightsubtree.right;
                        countr++;
                    }
    
                }
            }
    
            return countr >= countl ? countr : countl;
    
    
        }
于 2022-01-21T15:02:43.680 回答