这里默认树高/深都是树中结点的最大层数,根层数为1。
开始/递归终止都是:
if(T=NULL)
return 0;
一.递归
1.直接递归
终止条件:T==NULL; return 0;
循环体:以T为根的长度,是其左子树、右子树中长度大者+1
int Depth(BiTree T) {
if (T==NULL)
return 0;
else
return Depth(T->lchild) > Depth(T->rchild) ? Depth(T->lchild)+1 : Depth(T->rchild)+1;
}
一条语句就可以搞定:
int Depth(BiTree T) {
return T == NULL ? 0 : Depth(T->lchild) > Depth(T->rchild) ? Depth(T->lchild) + 1 : Depth(T->rchild) + 1;
}
2.递归遍历
将层数作为参数传入,每次递归都+1,到达叶子结点取最大的level-1
值为高
int depth = 1; //全局变量,记录高度
void high(BiTree T, int level) { //level初始值为1
if (T) {
high(T->lchild, level + 1);
high(T->rchild, level + 1);
}
else
depth = depth > level - 1 ? depth : level - 1; //到叶子的时候,取高的
}
将level作为参数传入,进行递归的遍历可以追踪每一层的情况。
二.非递归
1.层次遍历——队列
层次遍历每次遍历一层,我们可设变量level记录层数,设变量last记录每层最右边结点的位置,每次Q.front==last
,说明进入了下一层,即level++
int Depth(BiTree T) {
if (T == NULL)
return 0;
SqQueue Q;
InitQueue(Q); //Q.front=Q.rear=0;
BiNode* p = T;
int level = 0, last = 1; //默认front指向队首元素,rear指向队尾后一个
EnQueue(Q, T);
while (!isEmpty(Q)) {
DeQueue(Q, p);
cout << p->data;
if (p->lchild != NULL)
EnQueue(Q, p->lchild);
if (p->rchild != NULL)
EnQueue(Q, p->rchild);
if (Q.front == last) { //如果队首到了last
level++;
last = Q.rear;
}
}
}
我们只需要在原始代码上增加两个变量level = 0
,last = 1
,然后每次while末尾进队结束时判断是否 Q.front==last
,是level++;
,last = Q.rear;
if(Q.front==last){ //如果队首到了last
level++;
last=Q.rear;
}
层次遍历还可用于求某层结点数,每层结点个数,树的最大宽度,判断是否完全二叉树…
2.后序遍历——栈
因为后序遍历总是从根向下压栈,然后从下向上弹栈,根总是最后弹出。
在任一时刻,栈中都是一条根T到栈顶的路径,栈内的情况遍历了树根到其他任何结点的路径。那么最长路径必然也会出现。
我们只需要每次压栈记录下栈长,然后取最长的栈长即可。
int Depth(BiTree T) {
SqStack S;
InitStack(S);
BiNode* p = T, * r = NULL;
int depth = 0; //记录长度
while (p || !isEmpty(S)) {
if (p) {
push(S, p);
p = p->lchild;
depth = depth > S.top + 1 ? depth : S.top + 1; //每次压栈更新长度
}
else {
GetTop(S, p); //取栈顶分析
if (p->rchild && p->rchild != r)
p = p->rchild;
else {
pop(S, p);
cout << p->data;
r = p;
p = NULL;
}
}
}
}