《剑指offer》:[39-1]判断是否为平衡二叉树

题目:输入一棵二叉树的结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
上图中的二叉树就是一棵平衡二叉树。
分析:有了求二叉树深度的思路后,我们很快就能找到求解该问题的方法,就是从根结点开始开始判断其左右子结点的深度之差是否为1。如果从根结点开始到叶子结点的每一个结点的左右子树的深度相差都不超过1,则说明该二叉树是平衡二叉树。但是其时间复杂度接近O(N*N),因为里面有重复的遍历和访问。例如我们在判断8这个根结点是否是平衡的时候,我们需要判断其左右的两棵子树深度的差,需遍历3,5,7,6,但是当我们判断5结点是不是平衡的时候,我们还得遍历3,7,6这三个节点,所以重复的遍历使效率十分低下。还记得面试12(书上是面试9)中的斐波拉切数列的求法吗?典型的递归,但是那里的递归效率不高,和此题有相同的问题。
具体实现代码如下:
#include <iostream>
using namespace std;
struct BinaryTree
{
	int data;
	BinaryTree *pLeft;
	BinaryTree *pRight;
};
BinaryTree *pRoot1=NULL;
int arr[7]={8,5,15,3,7,16,6};
void InserTree(BinaryTree **root,int data)
{
	BinaryTree *temp=new BinaryTree;
	temp->data=data;
	temp->pLeft=temp->pRight=NULL;
	if(NULL==*root)
	{
		*root=temp;
	}
	else
	{
		BinaryTree *current=*root;
		BinaryTree *back=NULL;
		while(current)
		{
			back=current;
			if(data > current->data)
				current=current->pRight;
			else
				current=current->pLeft;
		}
		if(NULL==back->pLeft)
			back->pLeft=temp;
		else
			back->pRight=temp;
	}
}
void CreateTreeLoop(BinaryTree **root,int *array,int length)
{
	for(int i=0;i<length;i++)
		InserTree(root,array[i]);
}
void Inorder(BinaryTree *root)
{
	if(NULL!=root)
	{
		Inorder(root->pLeft);
		cout<<root->data<<" ";
		Inorder(root->pRight);
	}
}
int TreeDepth(BinaryTree*root)
{
	if(NULL==root)
		return 0;
	int left=TreeDepth(root->pLeft);
	int right=TreeDepth(root->pRight);
	return left>right?(left+1):(right+1);
}
bool IsBalance(BinaryTree *root)
{
	if(NULL==root)
		return true;
	int leftIsBla=TreeDepth(root->pLeft);
	int rightIsBla=TreeDepth(root->pRight);
	int diff=leftIsBla-rightIsBla;
	if(diff>1 || diff<-1  )
		return false;
	return IsBalance(root->pLeft) && IsBalance(root->pRight);
}


int main()
{
	CreateTreeLoop(&pRoot1,arr,7);
	cout<<"中序遍历:";
	Inorder(pRoot1);
	cout<<endl;
	bool result=IsBalanced(pRoot1);
	if(result)
		cout<<"The tree is balance!"<<endl;
	else
		cout<<"The tree is not a balance tree!"<<endl;
	system("pause");
	return 0;
}

运行结果:


   基于上面重复遍历效率较低的问题,我们对其进行了改进,通过后续遍历,从叶子结点->到根结点开始判断该树是不是平衡的。因为当我们在遍历某节点的左右子节点的左右子节点是否平衡后,我们相应的就得到了当前节点的深度,我们就不用重复遍历该树的一些节点,当最后遍历到树的根结点的时候,也就判断了整棵二叉树是不是平衡二叉树。
其是实现关键代码如下:
bool IsBalanceHelp(BinaryTree *root,int *depth)
{
	if(root==NULL)
	{
		*depth=0;
		return true;
	}
	int left,right;
	if(IsBalanceHelp(root->pLeft,&left)&& IsBalanceHelp(root->pRight,&right))
	{
		int diff=left-right;
		if(diff<=1 && diff>=-1)
		{
			*depth=1+(left>right?left:right); //当遍历每个结点时,记录下该结点的深度,下次就不用再遍历已经遍历过的结点;
			return true;
		}
	}
	return false;
}
bool IsBalanced(BinaryTree *root)
{
	int depth=0;
	return IsBalanceHelp(root,&depth);
}
次种算法避免了不必要的重复计算,对于数据量大的二叉树效率明显提高。





  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值