1.算法思想
使用非递归后序遍历+栈实现。设置当前工作指针p和上一次访问结点visitedNode,使用栈s保存当前正在遍历的结点,栈l保存最长分支。先移动至最左下结点,然后判断是否还有右子树。如果有则继续访问,否则输出当前栈顶元素,如果是叶子结点则判断是否为最长分支,最后修改visitedNode和p,继续对其余元素进行同样的操作。
2.定义结构体
typedef struct BiNode {
int data;
struct BiNode* lchild;
struct BiNode* rchild;
} BiNode,*BiTree;
3.函数实现
- s[MAXSIZE], l[MAXSIZE]:s存放当前访问结点,l存放最长分支结点。
- visitedNode, p:visitedNode为上一次的访问结点,p为当前访问结点,初始值均为根结点T。
- top, longest:top表示栈顶指针,longest表示当前最长元素的长度。
void postTravel(BiTree T) {
BiNode* s[MAXSIZE];
BiNode* l[MAXSIZE];
BiNode* visitedNode = T, *p = T;
int top = -1,longest = 0;
if(!T) {//如果二叉树为空则退出
return;
}
while(p || top != -1) {
while(p) {//p不为空,移动到最左下位置
s[++top] = p;
p = p->lchild;
}
p = s[top];//p无左子树,将p修改为当前栈顶结点
//当前栈顶结点存在右子树且右子树未被访问
if(p->rchild && p->rchild != visitedNode) {
//将其右子树入栈,并继续访问右子树的左孩子
p = p->rchild;
s[++top] = p;
p = p->lchild;
} else {//当前结点无左子树,其右子树不存在或者已经被访问,则需要出栈
p = s[top];//先获取该结点,暂不出栈
//如果该结点为叶子结点
if(!p->lchild && !p->rchild) {
//判断最大长度,将最长路径存入l中。长度为top+1,因为top从0开始
if(top + 1 > longest) {
int i = 0;
while(i < top + 1) {
l[i] = s[i];
i++;
}
longest = top + 1;//修改最大长度
}
}
top--;//出栈
//修改上次访问结点为当前结点p,并修改当前结点为NULL
visitedNode = p;
p = NULL;
}
}
//输出最长分支
printf("最长分支长度为:%d,数据元素为:\n",longest);
for(int i = 0; i < longest; i++) {
printf("%d\t",l[i]->data);
}
}
4.测试结果
使用如下二叉树进行测试:
测试结果如下:
5.完整代码
#include<stdio.h>
#include<malloc.h>
#define MAXSIZE 50
typedef struct BiNode {
int data;
struct BiNode* lchild;
struct BiNode* rchild;
} BiNode,*BiTree;
/*
思路:非递归后序遍历+栈
*/
void postTravel(BiTree T) {
BiNode* s[MAXSIZE];
BiNode* l[MAXSIZE];
BiNode* visitedNode = T, *p = T;
int top = -1,longest = 0;
if(!T) {
return;
}
while(p || top != -1) {
while(p) {//p不为空,移动到最左下位置
s[++top] = p;
p = p->lchild;
}
p = s[top];//无左子树,获取当前栈顶结点
//当前栈顶结点存在右子树且右子树未被访问
if(p->rchild && p->rchild != visitedNode) {
p = p->rchild;
s[++top] = p;
p = p->lchild;
} else {
p = s[top];
//该结点为叶子结点
if(!p->lchild && !p->rchild) {
//判断最大长度,将最长路径存入l中
if(top + 1 > longest) {
int i = 0;
while(i < top + 1) {
l[i] = s[i];
i++;
}
longest = top + 1;
}
}
top--;
visitedNode = p;
p = NULL;
}
}
//输出最长分支
printf("最长分支长度为:%d,数据元素为:\n",longest);
for(int i = 0; i < longest; i++) {
printf("%d\t",l[i]->data);
}
}
int main() {
BiTree l1 = (BiTree)malloc(sizeof(BiNode));
BiNode *l2 = (BiNode *)malloc(sizeof(BiNode));
BiNode *l3 = (BiNode *)malloc(sizeof(BiNode));
BiNode *l4 = (BiNode *)malloc(sizeof(BiNode));
BiNode *l5 = (BiNode *)malloc(sizeof(BiNode));
BiNode *l6 = (BiNode *)malloc(sizeof(BiNode));
BiNode *l7 = (BiNode *)malloc(sizeof(BiNode));
l1->data = 1;
l2->data = 2;
l3->data = 3;
l4->data = 4;
l5->data = 5;
l6->data = 6;
l7->data = 7;
l1->lchild = l2;
l1->rchild = l3;
l2->lchild = l4;
l2->rchild = l5;
l3->lchild = NULL;
l3->rchild = l6;
l4->lchild = NULL;
l4->rchild = l7;
l5->lchild = NULL;
l5->rchild = NULL;
l6->lchild = NULL;
l6->rchild = NULL;
l7->lchild = NULL;
l7->rchild = NULL;
postTravel(l1);
return 0;
}