您的位置:首页 > Web前端

【剑指offer】判断二叉树是否为平衡二叉树

2013-09-03 14:49 549 查看
2013-09-03 14:16:51

面试题39:求二叉树的深度、判断二叉树是否为平衡二叉树

小结:

根据平衡二叉树的定义,需要判断每个结点,因此,需要遍历二叉树的所有结点,并判断以当前结点为根的树是否为二叉树;

用后序遍历的方式,先判断左右子树是否为平衡的,在判断当前节点;

可以对每个结点求深度,根据深度判断,如函数IsBanlancedTreeBasic所示,但这种方法存在重复遍历,效率较低;

后序遍历时,一边判断是否为平衡二叉树,一边求而二叉树的深度,这样就避免了重复遍历,如函数IsBanlancedTree所示。

代码编写注意事项:

注意IsBanlancedTreeSub中需同时带回深度,因此在返回为true时,需要更新*pDepth的值;

写代码时,注意下面的代码由于优先级会造成错误

if ( (lchilDepth - rchilDepth) < -1 || (lchilDepth - rchilDepth) > 1)

因此改为:

int diff = lchilDepth - rchilDepth;
if ( diff < -1 || diff > 1)
{
return false;
}


代码(测试通过,暂未发现问题,欢迎交流指正):

#include <iostream>
#include <cassert>
using namespace std;

typedef char DataType;
const DataType LeafNode = '*';
const size_t SIZE = 1000;

typedef struct binaryTreeNode
{
DataType data;
binaryTreeNode *lchild;
binaryTreeNode *rchild;
}BTNode,*PBTNode;

//创建二叉树
PBTNode CreatBiTree(PBTNode &pRoot)
{
DataType newData = 0;

cin>>newData;

if (newData == LeafNode)
{
return NULL;
}

pRoot = new BTNode;
pRoot->data = newData;

pRoot->lchild = CreatBiTree(pRoot->lchild);
pRoot->rchild = CreatBiTree(pRoot->rchild);

return pRoot;
}

//访问二叉树结点
void VisitBiTreeNode(const PBTNode &pBTNode)
{
assert(NULL != pBTNode);
cout<<pBTNode->data<<"\t";
}

//前序遍历二叉树
void PreOrder(const PBTNode &pRoot)
{
if (pRoot != NULL)
{
VisitBiTreeNode(pRoot);
PreOrder(pRoot->lchild);
PreOrder(pRoot->rchild);
}
}

//中序遍历二叉树
void InOrder(const PBTNode &pRoot)
{
if (pRoot != NULL)
{
InOrder(pRoot->lchild);
VisitBiTreeNode(pRoot);
InOrder(pRoot->rchild);
}
}

//后序遍历二叉树
void PostOrder(const PBTNode &pRoot)
{
if (pRoot != NULL)
{
PostOrder(pRoot->lchild);
PostOrder(pRoot->rchild);
VisitBiTreeNode(pRoot);
}
}

//求二叉树深度
size_t GetDepthOfBiTree(const PBTNode &pRoot)
{
if (NULL == pRoot)
{
return 0;
}

size_t lchilDepth = GetDepthOfBiTree(pRoot->lchild);
size_t rchilDepth = GetDepthOfBiTree(pRoot->rchild);

return ( (lchilDepth > rchilDepth) ? (lchilDepth + 1) : (rchilDepth + 1) );
}

//判断是否平衡二叉树,求每个结点的深度,有重复遍历
bool IsBanlancedTreeBasic(const PBTNode &pRoot)
{
if (pRoot == NULL)   //若左子树为空,右子树的深度超过1,判断会出错
return true;

//return ( IsBanlancedTree(pRoot->lchild) && IsBanlancedTree(pRoot->rchild) );

if ( !IsBanlancedTreeBasic(pRoot->lchild) || !IsBanlancedTreeBasic(pRoot->rchild) )
{
return false;
}

size_t lchilDepth = GetDepthOfBiTree(pRoot->lchild);
size_t rchilDepth = GetDepthOfBiTree(pRoot->rchild);
int diff = lchilDepth - rchilDepth;
//if ( (lchilDepth - rchilDepth) < -1 || (lchilDepth - rchilDepth) > 1)
if ( diff < -1 || diff > 1)
{
return false;
}

return true;
}

//判断是否平衡二叉树,优化,没有重复遍历
bool IsBanlancedTreeSub(const PBTNode &pRoot,size_t *pDepth)
{
if (pRoot == NULL)
{
*pDepth = 0;
return true;
}

size_t lchildDepth = 0;
size_t rchildDepth = 0;

if ( !IsBanlancedTreeSub(pRoot->lchild,&lchildDepth) || !IsBanlancedTreeSub(pRoot->rchild,&rchildDepth) )
{
return false;
}

int diff = lchildDepth - rchildDepth;

if ( diff < -1 || diff > 1)
{
return false;
}

*pDepth = lchildDepth > rchildDepth ? (lchildDepth + 1) : (rchildDepth + 1);
return true;
}

bool IsBanlancedTree(const PBTNode &pRoot)
{
size_t Depth = 0;
return IsBanlancedTreeSub(pRoot,&Depth);
}

void DestoryBiTreeNode(PBTNode pRoot)
{
delete pRoot;
}

//销毁二叉树
void DestoryBiTree(PBTNode &pRoot)
{
if (pRoot != NULL)
{
DestoryBiTree(pRoot->lchild);
DestoryBiTree(pRoot->rchild);
DestoryBiTreeNode(pRoot);
}
}

//测试二叉树相关操作
void TestBinaryTree()
{
PBTNode pRoot = NULL;

cout<<"Test IsBanlancedTree..."<<endl;

//测试IsBanlancedTree
while (1)
{
cout<<"Please enter the binary tree,'*' for leaf node"<<endl;
CreatBiTree(pRoot);

//Test PreOrder...
//cout<<"Test PreOrder..."<<endl;
cout<<"The pre order is :"<<endl;
PreOrder(pRoot);
cout<<endl;

//Test InOrder...
//cout<<"Test InOrder..."<<endl;
cout<<"The in order is :"<<endl;
InOrder(pRoot);
cout<<endl;

//Test PostOrder...
//cout<<"Test PostOrder..."<<endl;
cout<<"The post order is :"<<endl;
PostOrder(pRoot);
cout<<endl;

cout<<"IsBanlancedTree : "<<IsBanlancedTree(pRoot)<<endl;
cout<<"IsBanlancedTreeBasic : "<<IsBanlancedTreeBasic(pRoot)<<endl;

cout<<"Test DestoryBiTree..."<<endl;
DestoryBiTree(pRoot);
}

/*cout<<"Test DestoryBiTree..."<<endl;
DestoryBiTree(pRoot);*/
}

int main()
{
TestBinaryTree();
return 0;
}


测试结果:

Test IsBanlancedTree...
Please enter the binary tree,'*' for leaf node
ab**c**
The pre order is :
a       b       c
The in order is :
b       a       c
The post order is :
b       c       a
IsBanlancedTree : 1
IsBanlancedTreeBasic : 1
Test DestoryBiTree...
Please enter the binary tree,'*' for leaf node
ab***
The pre order is :
a       b
The in order is :
b       a
The post order is :
b       a
IsBanlancedTree : 1
IsBanlancedTreeBasic : 1
Test DestoryBiTree...
Please enter the binary tree,'*' for leaf node
a**
The pre order is :
a
The in order is :
a
The post order is :
a
IsBanlancedTree : 1
IsBanlancedTreeBasic : 1
Test DestoryBiTree...
Please enter the binary tree,'*' for leaf node
abc****
The pre order is :
a       b       c
The in order is :
c       b       a
The post order is :
c       b       a
IsBanlancedTree : 0
IsBanlancedTreeBasic : 0
Test DestoryBiTree...
Please enter the binary tree,'*' for leaf node
abcd****e*f**
The pre order is :
a       b       c       d       e       f
The in order is :
d       c       b       a       e       f
The post order is :
d       c       b       f       e       a
IsBanlancedTree : 0
IsBanlancedTreeBasic : 0
Test DestoryBiTree...
Please enter the binary tree,'*' for leaf node
abd**e**cf***
The pre order is :
a       b       d       e       c       f
The in order is :
d       b       e       a       f       c
The post order is :
d       e       b       f       c       a
IsBanlancedTree : 1
IsBanlancedTreeBasic : 1
Test DestoryBiTree...
Please enter the binary tree,'*' for leaf node
**
The pre order is :
请按任意键继续. . .
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: