题目:输入一棵二叉树的结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过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); }
次种算法避免了不必要的重复计算,对于数据量大的二叉树效率明显提高。
时间: 2024-10-20 14:26:15