题目要求 :
本题要求给定二叉树的高度。
函数接口定义:
int GetHeight( BinTree BT );
要求函数返回给定二叉树BT的高度值。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
BinTree CreatBinTree(); /* 实现细节忽略 */
int GetHeight( BinTree BT );
int main()
{
BinTree BT = CreatBinTree();
printf("%d\n", GetHeight(BT));
return 0;
}
/* 你的代码将被嵌在这里 */
实现代码:
递归:
int GetHeight(BinTree t){
if(t==NULL) return 0;//当节点为空时返回0
int l=GetHeight(t->Left);//递归计算所有左子树的高度
int r=GetHeight(t->Right);//递归计算所有右子树的高度
return (l>r?l:r)+1;//返回左树或右树的最大高度
}
函数具体实现过程:
以题目给出的二叉树为例:
每次递归时返回左右子树高度的最大值+1。
非递归:
typedef struct stack{
BinTree ptr[100];//定义存储节点指针的栈
int top;
}Stack;
Stack* create(){
//初始化栈
Stack* s=(Stack*)malloc(sizeof(Stack));
s->top=-1;
return s;
}
//压栈
void push(Stack* s,BinTree ptr){
s->ptr[++s->top]=ptr;
}
//出栈
void pop(Stack* s){
s->top--;
}
//辅助函数 判断栈空
int isEmpty(Stack* s){
return s->top==-1;
}
int GetHeight(BinTree t){
//遍历,直至栈和节点为空
int height=0;
int current_height=0;
//初始化局部高度和总高度
BinTree current=t;//当前节点
BinTree last=NULL;//上一个处理的节点,初始化为NULL
Stack* s=create();//创建栈
while(current||!isEmpty(s)){
while(current){
push(s,current);//当前节点不为NULL,压入栈顶
current=current->Left;//更新当前节点为左孩子
current_height++;//当前高度自增
}
current=s->ptr[s->top];//当节点的左孩子为空
//将当前节点设置为栈顶节点,但不弹出,暂时保存栈顶节点
if(current->Right&&last!=current->Right){
//当前节点的右孩子存在,且未被处理
current=current->Right;//更新节点为右孩子
}
else{
if(current_height>height) height=current_height;
//更新总高度
pop(s);//栈顶节点出栈
last=current;//更新上一个处理的节点
current_height--;//回溯高度
current=NULL;//强制退出内层循环,处理下一个节点
}
}
free(s);//释放栈的内存
return height;//返回总高度
}
实现过程:
假设有如下二叉树:
A
/ \
B C
/ \ \
D E F
遍历过程
步骤 当前节点 栈状态(从底到顶) current_height
height
操作 1 A [A] 1 0 左转B 2 B [A, B] 2 0 左转D 3 D [A, B, D] 3 0 D无左/右 4 D [A, B, D] 3 3 回溯到B 5 B [A, B] 2 3 右转E 6 E [A, B, E] 3 3 E无左/右 7 E [A, B, E] 3 3 回溯到B 8 B [A, B] 2 3 回溯到A 9 A [A] 1 3 右转C 10 C [A, C] 2 3 C无左,右转F 11 F [A, C, F] 3 3 F无左/右 12 F [A, C, F] 3 3 回溯到C 13 C [A, C] 2 3 回溯到A 14 A [A] 1 3 栈空,结束 最终返回
height = 3
(最长路径A→B→D
或A→C→F
)。
总结:
1、递归实现只适合处理规模不大的树。
2、非递归实现则可以处理大规模数据,但是在这一段代码中定义了一个last的变量来存储上一个处理的节点,使得逻辑变得更复杂。
可以在栈中增加一个数组来存储各节点的高度并随弹栈更新。