题目一:输入一课二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
二叉树的结点定义如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
}
思路:如果一棵树只有一个结点,它的深度为1。如果根结点只有左子树而没有右子树,那么树的深度应该是左子树的深度加1;同样如果结点只有右子树而没有左子树,那么树的深度应该是其右子树的深度加1;如果有左子树和右子树,深度就是左右子树的较大值加1。代码如下:int TreeDept(BinaryTreeNode* pRoot)
{
if(pRoot==NULL)
return 0;
int left=TreeDept(pRoot->m_pLeft);
int right=TreeDept(pRoot->m_pRight);
return (left>right)?(left+1):(right+1);
}
测试用例:
功能测试(输入普通的二叉树,二叉树中所有结点都没有左/右子树)
特殊输入测试(二叉树只有一个结点,二叉树的头结点为NULL指针)。
题目二:输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
分析:
解法一:需要重复遍历结点多次的解法
有了求二叉树深度的经验之后,我们很容易想到一个思路:在遍历树的每一个结点的时候,调用TreeDepth得到它的左右子树的深度。如果每一个结点的左右子树的深度相差不超过1,按照定义它就是一棵平衡二叉树。这种思路对应代码如下:
bool IsBalanced(BinaryTreeNode* pRoot)
{
if(pRoot==NULL)
return true;
int left=TreeDept(pRoot->m_pLeft);
int right=TreeDept(pRoot->m_pRight);
int diff=left-right;
if(diff>1 || diff<-1)
return false;
return IsBalanced(pRoot->m_pLeft) && IsBalanced(pRoot->m_pRight);
}
上面的代码虽然简洁,但是我们也要注意到由于一个结点会被重复遍历多次,这种思路的时间效率不高。解法二:每一个结点只遍历一次的解法
如果我们使用后序遍历的方式遍历二叉树的每一个结点,在遍历的一个结点之前我们就已经遍历了它的左右子树。只要在遍历每一个结点的时候记录它的深度(某一个结点的深度等于它到叶子结点的路径的长度),我们就可以一边遍历,一边判断每一个结点是不是平衡的。代码如下:
bool IsBalanced(BinaryTreeNode* pRoot,int* pDept)
{
if(pRoot==NULL )
{
*pDept=0;
return true;
}
int left;
int right;
if(IsBalanced(pRoot->m_pLeft,&left)&&IsBalanced(pRoot->m_pRight,&right))
{
int diff=left-right;
if(diff>=1 || diff<=-1)
{
*pDept=1+(left>right?left:right);
return true;
}
}
return false;
}
我们只需要给上面的函数传入二叉树的根结点以及表示结点深度的整型变量即可:bool IsBalanced(BinaryTreeNode* pRoot)
{
int dept=0;
return IsBalanced(pRoot,&dept);
}
测试用例:功能测试(平衡二叉树,不是平衡二叉树,二叉树中所有结点都没有左右子树)
特殊输入测试(二叉树中只有一个结点,二叉树的头结点为NULL指针)