第4章第1节练习题4 二叉树高度和宽度统计
来源:互联网 发布:js透明度渐变 编辑:程序博客网 时间:2024/06/05 00:48
为了方便说明二叉树的递归传值过程,这里首先给出一个基本的二叉树结构。
图中值为NULL的节点实际是不存在的,故与父亲节点之间的连接用灰色的虚线表示。只是为了便于说明,才假设了一个NULL的空节点。
以下图中,黄色的线表明了传值的方向;绿色的数值表明了子节点传到父亲节点时的值,即根据递归公式计算便可。
一.计算二叉树的高度(递归/非递归)
递归方式实现
对于高度的计算,首先是从叶子结点算起,假设叶子结点下面的NULL节点高度为0,则叶子结点的高度便为1,那么叶子结点的双亲节点便为2,以此类推便可以得到根节点的高度,这样也就得到了整棵二叉树的高度。其基本的递归公式如下:
具体执行过程可以参考下图,
当指针遍历到叶子结点的孩子结点(NULL结点)时,向叶子结点返回0,然后由叶子结点判断来自左边的孩子结点(NULL结点)和来自右边的孩子结点(其实还是NULL结点)的返回值谁比较大,因为叶子结点处的值均由NULL结点返回,因此相等,则取右边NULL结点的值,然后+1,表示叶子结点的高度。然后再由叶子结点向其双亲节点返回值,依次类推便可以得到整棵树的高度。
算法描述如下
int CntHeight_recursive(BiTNode* T){ int lh,rh; if(T==NULL){ return 0; } lh=CntHeight_recursive(T->lchild); rh=CntHeight_recursive(T->rchild); return lh>rh?lh+1:rh+1;}
非递归方式实现
采用层次遍历的算法,设置变量cnt表示当前结点所在层次,设置变量last指向当前层最右结点,每次层次遍历出队时与last相比较,如果两者相等,那么层数+1,并让last指向下一层最右结点,直至遍历完成。level的值即为二叉树的高度。
关于last指针的特性应该注意到,当队首指针front指向last标识符时,其队尾指针rear刚好会指向下一层的队尾元素。
算法描述如下
int CntHeight_norecursive(BiTNode* T){ BiTNode* p=T; SqQueue Q; InitQueue(&Q); EnQueue(&Q,p); int cnt=0; int last=1; while(IsEmptyQueue(&Q)!=0){ p=DeQueue(&Q); if(p->lchild!=NULL){ EnQueue(&Q,p->lchild); } if(p->rchild!=NULL){ EnQueue(&Q,p->rchild); } if(Q.front==last){ cnt++; last=Q.rear; } } return cnt;}
二.计算二叉树的宽度(非递归)
关于递归方式,个人没有想到特别好的解决方案,这里主要以非递归方式实现。
非递归方式的实现方式与计算二叉树宽度的非递归实现方式类似,完全可以利用last指针的特性,即当队首指针front指向last时,此时队尾指针rear会刚好指向二叉树下一层的最右边结点,此时只需要用队尾指针rear减去队首指针便可以得到该层的宽度。而二叉树的宽度则指的是从根节点到叶子结点的某层中元素最多的一层,因此只需要将每层的宽度保存下来取最大值便可。
非递归方式实现
int CntWidth_norecursive(BiTNode* T){ BiTNode* p=T; SqQueue Q; InitQueue(&Q); EnQueue(&Q,p); int cnt=0; int last=1; int level[MaxSize]={0}; while(IsEmptyQueue(&Q)!=0){ p=DeQueue(&Q); if(p->lchild!=NULL){ EnQueue(&Q,p->lchild); } if(p->rchild!=NULL){ EnQueue(&Q,p->rchild); } if(Q.front==last){ level[cnt++]=Q.rear-Q.front; last=Q.rear; } } int max=level[0]; for(int i=0;i<cnt;i++){ if(max<level[i]){ max=level[i]; } } return max;}
具体代码见附件。
附件
//统计二叉树的高度和宽度//AB#DG###CE##F###include<stdio.h>#include<stdlib.h>#define MaxSize 10typedef char ElemType;typedef struct BiTNode{ ElemType data; struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;typedef struct{ BiTNode* data[MaxSize]; int front, rear;}SqQueue;BiTNode* CreateBiTree(BiTNode*);void InitQueue(SqQueue*);void EnQueue(SqQueue*,BiTNode*);BiTNode* DeQueue(SqQueue*);int IsEmptyQueue(SqQueue*);void PreOrder(BiTNode*);void InOrder(BiTNode*);int CntHeight_recursive(BiTNode*);int CntHeight_norecursive(BiTNode*);int CntWidth_norecursive(BiTNode*);//-------------------------------------------------------------------------------------int main(int argc, char* argv[]){ BiTNode* T=(BiTNode*)malloc(sizeof(BiTNode)); T=CreateBiTree(T); PreOrder(T);printf("\n"); InOrder(T);printf("\n"); int count; count=CntHeight_recursive(T); printf("recursive:The height of BiTree is %d\n",count); count=CntHeight_norecursive(T); printf("non-recursive:The height of BiTree is %d\n",count); count=CntWidth_norecursive(T); printf("non-recursive:The Width of BiTree is %d\n",count); return 0;}//-------------------------------------------------------------------------------------BiTNode* CreateBiTree(BiTNode* T){ ElemType ch; scanf("%c",&ch); if(ch=='#'){ return NULL; } T=(BiTNode*)malloc(sizeof(BiTNode)); T->data=ch; T->lchild=CreateBiTree(T->lchild); T->rchild=CreateBiTree(T->rchild); return T;}//-------------------------------------------------------------------------------------//统计二叉树的高度(递归)int CntHeight_recursive(BiTNode* T){ int lh,rh; if(T==NULL){ return 0; } lh=CntHeight_recursive(T->lchild); rh=CntHeight_recursive(T->rchild); return lh>rh?lh+1:rh+1;}//统计二叉树的高度(非递归)int CntHeight_norecursive(BiTNode* T){ BiTNode* p=T; SqQueue Q; InitQueue(&Q); EnQueue(&Q,p); int cnt=0; int last=1; while(IsEmptyQueue(&Q)!=0){ p=DeQueue(&Q); if(p->lchild!=NULL){ EnQueue(&Q,p->lchild); } if(p->rchild!=NULL){ EnQueue(&Q,p->rchild); } if(Q.front==last){ cnt++; last=Q.rear; } } return cnt;}//-------------------------------------------------------------------------------------//统计二叉树的宽度(非递归)int CntWidth_norecursive(BiTNode* T){ BiTNode* p=T; SqQueue Q; InitQueue(&Q); EnQueue(&Q,p); int cnt=0; int last=1; int level[MaxSize]={0}; while(IsEmptyQueue(&Q)!=0){ p=DeQueue(&Q); if(p->lchild!=NULL){ EnQueue(&Q,p->lchild); } if(p->rchild!=NULL){ EnQueue(&Q,p->rchild); } if(Q.front==last){ level[cnt++]=Q.rear-Q.front; last=Q.rear; } } int max=level[0]; for(int i=0;i<cnt;i++){ if(max<level[i]){ max=level[i]; } } return max;}//-------------------------------------------------------------------------------------//先序遍历void PreOrder(BiTNode* T){ if(T==NULL){ return; } printf("%c",T->data); PreOrder(T->lchild); PreOrder(T->rchild);}//中序遍历void InOrder(BiTNode* T){ if(T==NULL){ return; } InOrder(T->lchild); printf("%c",T->data); InOrder(T->rchild);}//-------------------------------------------------------------------------------------void InitQueue(SqQueue* Q){ Q->front=0; Q->rear=0;}void EnQueue(SqQueue* Q, BiTNode* T){ if((Q->rear+1)%MaxSize==Q->front){ return; } Q->data[Q->rear++]=T;}BiTNode* DeQueue(SqQueue* Q){ if(Q->front==Q->rear){ return NULL; } return Q->data[Q->front++];}int IsEmptyQueue(SqQueue* Q){ if(Q->rear==Q->front){ return 0; }else{ return -1; }}
- 第4章第1节练习题4 二叉树高度和宽度统计
- 第4章第1节练习题3 二叉树特殊节点个数统计
- 第4章第1节练习题13 根据先序序列和中序序列建立二叉树
- 第4章第1节练习题1 二叉树的基本操作(递归实现)
- 第4章第1节练习题7 交换二叉树所有节点左右子树
- 第4章第1节练习题15 判断两颗二叉树是否相似
- 第4章第1节练习题5 二叉树查找第k个结点的值
- 第4章第1节练习题10 判断某二叉树是否为完全二叉树
- 第4章第1节练习题6 二叉树叶子节点链接成单链表
- 第4章第1节练习题2 二叉树的基本操作(非递归实现)
- 第4章第1节练习题14 满二叉树已知先序序列求解后序序列
- 二叉树宽度和高度
- 第4章第1节 二叉树的基本概念
- 第4章 树和二叉树
- 第3章练习题4
- [WikiOI] 2.6.1 二叉树最大宽度和高度
- 树 二叉树最大宽度和高度
- 二叉树最大宽度和高度
- VIM 编辑器的使用_1
- Problem A: C语言习题 字符串长度
- springMVC下导出Excel功能
- 二叉树的前序遍历---非递归实现
- javascript标准对象
- 第4章第1节练习题4 二叉树高度和宽度统计
- svn 简单使用
- mac终端命令大全介绍2
- JavaScript 与html的元素产生关联
- There was an internal Api failed
- GCD-同步,异步分别在串行队列,并发队列,主队列下的执行方式
- VIM 编辑器的使用_2
- Dll注入--修改PE文件头
- 204. Count Primes 统计素数