【数据结构】设二叉树T,用二叉链表结构存储。编写函数,输出最长一支(根到叶子)上的所有结点值

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;
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天进步一点丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值