判断一棵树是否是平衡二叉树

题目:编程题-平衡二叉树
时间限制 1000 ms,内存限制 256000 kB,代码长度限制 8000 B
判断一个二叉树是不是平衡
说明:一棵二叉树任意一个节点的左右子树的深度差不大于1,即为平衡二叉树。
给定一个有N个节点的二叉树,每个节点有一个序号表示,树有M条分支。每个分支用三个数字A B C表示,指A节点的左儿子为B,右儿子为C。如果B或C为-1,说明无该儿子。
规定树根的序号为1,树的节点数目最多不超过50000。
每个测试数据有多组case。
对于每个case,第一行先输入N和M。然后下面M行每行代表一个分支。
对于每个case输出为一行,如果该树是平衡二叉树,请输出1,否则输出0
每个case之间不需要空行隔开,如以下示例
输入示例
11 5
5 6 7
4 10 11
3 8 9
1 2 3
2 4 5
13 6
6 7 8
2 3 4
10 11 12
8 9 10
1 2 13
4 5 6
输出示例
1
0
分析:题目可以分解成两个问题:
1、根据输入数据组织二叉树;
2、判断平衡二叉树。
针对问题1:由于每个结点序号已事先固定,可以使用数组来表示,数组下标即为结点序号。对于每个结点的左右孩子的表示,可以定义两个数组,分别是leftChild[]左孩子数组,rightChild[]右孩子数组,结点i的左孩子为leftChild[i],右孩子为rightChild[i];也可以定义一个结构体 struct Node {int leftChild; int rightChild;},再定义结点数组biTree[],如此结点i的左右孩子即为biTree[i].leftChild, biTree[i].rightChild。
[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <queue>  
  3.   
  4. struct Node {  
  5.     int leftChild;  
  6.     int rightChild;  
  7.   
  8.     Node() {  
  9.         leftChild  = -1;  
  10.         rightChild = -1;  
  11.     }  
  12. };  

针对问题2:参考《剑指Offer》有两种方法,
方法一:判断二叉树是否平衡与求取每个结点的深度分离,此方法简单直观,但效率不高,每个结点在判断平衡和求取深度的时候都被重复遍历
[cpp]  view plain copy
  1. int DepthOfBiTree(Node biTree[], int i) {  
  2.     int leftDepth, rightDepth;  
  3.     if (i == -1)  
  4.         return 0;  
  5.   
  6.     leftDepth  = 1 + DepthOfBiTree(biTree, biTree[i].leftChild);  
  7.     rightDepth = 1 + DepthOfBiTree(biTree, biTree[i].rightChild);  
  8.   
  9.     return leftDepth > rightDepth ? leftDepth : rightDepth;  
  10. }  
  11.   
  12. bool IsBalanceBiTree(Node biTree[], int i) {  
  13.     if (i == -1)  
  14.         return true;  
  15.     int diff = DepthOfBiTree(biTree, biTree[i].leftChild)   
  16.                 - DepthOfBiTree(biTree, biTree[i].rightChild);  
  17.     if (diff > 1 || diff < -1)  
  18.         return false;  
  19.     else   
  20.         return IsBalanceBiTree(biTree, biTree[i].leftChild)   
  21.                  && IsBalanceBiTree(biTree, biTree[i].rightChild);   
  22. }  

方法二:判断二叉树是否平衡和求取结点深度统一,此时避免了上面的问题
[cpp]  view plain copy
  1. bool IsBalanceBiTree(Node biTree[], int i, int *depth) {  
  2.     if (i == -1) {  
  3.         *depth = 0;  
  4.         return true;  
  5.     }  
  6.     int leftDepth, rightDepth;  
  7.     if (IsBalanceBiTree(biTree, biTree[i].leftChild, &leftDepth)  
  8.         && IsBalanceBiTree(biTree, biTree[i].rightChild, &rightDepth)) {  
  9.             int diff = leftDepth - rightDepth;  
  10.             if (diff >= -1 && diff <= 1) {  
  11.                 *depth = 1 + (leftDepth > rightDepth ? leftDepth : rightDepth);  
  12.                 return true;  
  13.             }  
  14.     }  
  15.     return false;  
  16. }  
  17.   
  18. bool IsBalanceBiTree(Node biTree[]) {  
  19.     int depth = 0;  
  20.     return IsBalanceBiTree(biTree, 1, &depth);  
  21. }  

读取数据的函数,以(0,0)结束:
[cpp]  view plain copy
  1. void ReadData() {  
  2.     std::queue<bool> result;  
  3.     while (true) {     
  4.         int N, M;  
  5.         if (scanf("%d %d", &N, &M) != 2) break;  
  6.   
  7.         if (N <= 0 || M <= 0) break;  
  8.         Node *biTree = new Node[N + 1];  
  9.   
  10.         int parent, leftChild, rightChild;  
  11.         for (int i = 0 ; i < M; ++ i) {  
  12.             scanf("%d %d %d", &parent, &leftChild, &rightChild);  
  13.             biTree[parent].leftChild = leftChild;  
  14.             biTree[parent].rightChild = rightChild;  
  15.         }  
  16.         if (IsBalanceBiTree(biTree))  
  17.             result.push(true);  
  18.         else   
  19.             result.push(false);  
  20.   
  21.         delete[] biTree;  
  22.         biTree = NULL;  
  23.     }  
  24.     while (!result.empty()) {  
  25.              printf("%d\n", result.front());  
  26.              result.pop();  
  27.     }  
  28. }  

PS:有道,机试,2013,校招
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值