判断二叉树是不是平衡

简介:

平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

题目:输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

例如下图中的二叉树就是一棵平衡二叉树:

 

本系列博客的第27题,我们曾介绍过如何求二叉树的深度。有了求二叉树的深度的经验之后再解决这个问题,我们很容易就能想到一个思路:在遍历树的每个结点的时候,调用函数TreeDepth得到它的左右子树的深度。如果每个结点的左右子树的深度相差都不超过1,按照定义它就是一棵平衡的二叉树

这种思路对应的代码如下:

 

int  TreeDepth(SBinaryTreeNode *pTreeNode)
{
       if (!pTreeNode)
             return  0;
  
       int  nLeft = TreeDepth(pTreeNode->m_pLeft);
       int  nRight = TreeDepth(pTreeNode->m_pRight);
  
       return  (nLeft > nRight) ? (nLeft + 1) : (nRight + 1);
}

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
bool  IsBalanced(BinaryTreeNode* pRoot)
{
     if (pRoot == NULL)
         return  true ;
 
     int  left = TreeDepth(pRoot->m_pLeft);
     int  right = TreeDepth(pRoot->m_pRight);
     int  diff = left - right;
     if (diff > 1 || diff < -1)
         return  false ;
 
     return  IsBalanced(pRoot->m_pLeft) && IsBalanced(pRoot->m_pRight);
}

 

 

上面的代码固然简洁,但我们也要注意到由于一个节点会被重复遍历多次,这种思路的时间效率不高。例如在函数IsBalance中输入上图中的二叉树,首先判断根结点(值为1的结点)的左右子树是不是平衡结点。此时我们将往函数TreeDepth输入左子树根结点(值为2的结点),需要遍历结点457。接下来判断以值为2的结点为根结点的子树是不是平衡树的时候,仍然会遍历结点457。毫无疑问,重复遍历同一个结点会影响性能。接下来我们寻找不需要重复遍历的算法。

如果我们用后序遍历的方式遍历二叉树的每一个结点,在遍历到一个结点之前我们已经遍历了它的左右子树。只要在遍历每个结点的时候记录它的深度(某一结点的深度等于它到叶节点的路径的长度),我们就可以一边遍历一边判断每个结点是不是平衡的。

下面是这种思路的参考代码:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
bool  IsBalanced(BinaryTreeNode* pRoot,  int * pDepth)
{
     if (pRoot == NULL)
     {
         *pDepth = 0;
         return  true ;
     }
 
     int  left, right;
     if (IsBalanced(pRoot->m_pLeft, &left)
         && IsBalanced(pRoot->m_pRight, &right))
     {
         int  diff = left - right;
         if (diff <= 1 && diff >= -1)
         {
             *pDepth = 1 + (left > right ? left : right);
             return  true ;
         }
     }
 
     return  false ;
}

 

 我们只需要给上面的函数传入二叉树的根结点以及一个表示结点深度的整形变量就可以了:

1
2
3
4
5
bool  IsBalanced(BinaryTreeNode* pRoot)
{
     int  depth = 0;
     return  IsBalanced(pRoot, &depth);
}

 在上面的代码中,我们用后序遍历的方式遍历整棵二叉树。在遍历某结点的左右子结点之后,我们可以根据它的左右子结点的深度判断它是不是平衡的,并得到当前结点的深度。当最后遍历到树的根结点的时候,也就判断了整棵二叉树是不是平衡二叉树了。




本文转自夏雪冬日博客园博客,原文链接:http://www.cnblogs.com/heyonggang/p/3417779.html,如需转载请自行联系原作者

目录
相关文章
|
4月前
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树1
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树
|
存储 算法
算法训练Day17|● 104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
算法训练Day17|● 104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
2-3-4树是如何解决二叉树中非平衡问题的?
2-3-4树是如何解决二叉树中非平衡问题的?
从前序与中序遍历序列构造二叉树(中等难度)
从前序与中序遍历序列构造二叉树(中等难度)
91 0
从前序与中序遍历序列构造二叉树(中等难度)
|
测试技术
#### [623. 在二叉树中增加一行](https://leetcode.cn/problems/add-one-row-to-tree/)
#### [623. 在二叉树中增加一行](https://leetcode.cn/problems/add-one-row-to-tree/)
|
测试技术
#### [623. 在二叉树中增加一行]
#### [623. 在二叉树中增加一行](https://leetcode.cn/problems/add-one-row-to-tree/)
从中序与后序遍历序列构造二叉树(中等难度)
从中序与后序遍历序列构造二叉树(中等难度)
94 0
二叉树——530.二叉搜索树的最小绝对差
本专栏按照数组—链表—哈希—字符串—栈与队列—二叉树—回溯—贪心—动态规划—单调栈的顺序刷题,采用代码随想录所给的刷题顺序,一个正确的刷题顺序对算法学习是非常重要的,希望对大家有帮助
二叉树——530.二叉搜索树的最小绝对差
Day16——二叉树的最大深度、二叉树的最小深度、完全二叉树的节点个数
Day16——二叉树的最大深度、二叉树的最小深度、完全二叉树的节点个数
114 0