【数据结构】设有一家谱树,使用孩子兄弟(二叉链表)表示,编写函数,输出家谱中有多少代以及最后一代人数和成员名字

该文章介绍了一种使用层次遍历和队列的方法来找出二叉链表(孩子兄弟表示法)的最后一层节点。通过定义结构体BiNode,存储每个节点的孩子和右兄弟,然后利用层次遍历策略,将节点入队、出队,并模拟逻辑栈来存储每一层的节点。最后输出树的高度和最后一层的节点信息。
摘要由CSDN通过智能技术生成

1. 算法思想

根据二叉链表可以知道某个结点的所有孩子。因此基本思想是使用层次遍历+队列,每次都将某结点的所有孩子入队,然后再将结点出队存入到逻辑栈中。每遍历一层都让层数+1,直到最后一层退出循环。

2.定义结构体

typedef struct BiNode {
    struct BiNode *firstChild; //第一个孩子
    char data;                 //数据元素
    struct BiNode *rightSib;   //该结点的右兄弟
} BiNode, *BiTree;

3.函数实现

3.1 参数说明

  • p:工作指针
  • front,rear: 队列的队头和队尾,初始值为-1,表示为空
  • last, level: last表示每层的最后一个结点,当访问到该结点时应该让level++;level为当前层数
  • count: 表示最后一层有多少人
  • top: 表示栈顶元素,初始为-1,表示空

3.2 实现过程

  1. 首先将根结点入队,然后当front < rear时,将结点出队,即将该层结点全部出队,每出一个结点都要将他的所有孩子入队。
  2. 出队时,++front,移动队头指针。然后将top++,即模拟入栈操作,此时从栈顶到栈底模拟存放的是该层结点的倒序排列。然后将该结点的所有孩子全部入队。
  3. 当访问到该层的最后一个结点,即front == last时,将层数level+1,修改last为下一层的最后一个结点,即last = rear。判断当前层数是否为最后一层,如果不为最后一层,那么rear > front,修改count为count = rear - front
  4. 循环上述操作,直到遍历完最后一层。然后从top处输出最后一层结点,个数为count。
void LastGeneration(BiTree T) {
    BiNode *Q[MAXSIZE], *p = NULL;
    int front = -1, rear = -1; //队头和队尾
    int last = 0, level = 0;   //每层最后一个结点以及层数
    int count = 1;             //最后一层个数
    int top = -1; //用于实现逻辑栈,最后从栈顶开始输出最后一层的结点
    if (!T) {
        return;
    }
    Q[++rear] = T;         //根结点入队
    while (front < rear) { //出队
        p = Q[++front];
        top++;               //模拟入栈
        if (p->firstChild) { //有孩子则入队
            p = p->firstChild;
            Q[++rear] = p;
            while (p->rightSib) { //其余孩子也入队
                p = p->rightSib;
                Q[++rear] = p;
            }
        }
        if (last == front) { //访问到该层最后一个结点
            level++;
            last = rear;
            if (rear > front) { //此时还没到最后一层
                count = rear - front;
            }
        }
    }
    printf("共有%d代,最后一代有%d个人\n", level, count);
    printf("最后一代人为:\n");
    for (int i = count; i > 0; i--) {
        printf("%c\t", Q[top--]->data);
    }
}

4.运行结果

使用如下树:
在这里插入图片描述
输出的结果如下:
在这里插入图片描述

5.完整代码

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
/*
孩子兄弟表示法求树的高度,并输出最后一层的数量以及成员
借助层次遍历+队列
*/
typedef struct BiNode {
    struct BiNode *firstChild; //第一个孩子
    char data;                 //数据元素
    struct BiNode *rightSib;   //该结点的右兄弟
} BiNode, *BiTree;

void LastGeneration(BiTree T) {
    BiNode *Q[MAXSIZE], *p = NULL;
    int front = -1, rear = -1; //队头和队尾
    int last = 0, level = 0;   //每层最后一个结点以及层数
    int count = 1;             //最后一层个数
    int top = -1; //用于实现逻辑栈,最后从栈顶开始输出最后一层的结点
    if (!T) {
        return;
    }
    Q[++rear] = T;         //根结点入队
    while (front < rear) { //出队
        p = Q[++front];
        top++;               //模拟入栈
        if (p->firstChild) { //有孩子则入队
            p = p->firstChild;
            Q[++rear] = p;
            while (p->rightSib) { //其余孩子也入队
                p = p->rightSib;
                Q[++rear] = p;
            }
        }
        if (last == front) { //访问到该层最后一个结点
            level++;
            last = rear;
            if (rear > front) { //此时还没到最后一层
                count = rear - front;
            }
        }
    }
    printf("共有%d代,最后一代有%d个人\n", level, count);
    printf("最后一代人为:\n");
    for (int i = count; i > 0; i--) {
        printf("%c\t", Q[top--]->data);
    }
}

int main(int argc, char const *argv[]) {
    /* code */
    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));
    l1->data = 'A';
    l2->data = 'B';
    l3->data = 'C';
    l4->data = 'D';
    l5->data = 'E';
    l6->data = 'F';
    l1->firstChild = l2;
    l1->rightSib = NULL;
    l2->firstChild = l4;
    l2->rightSib = l3;
    l3->firstChild = l6;
    l3->rightSib = NULL;
    l4->firstChild = NULL;
    l4->rightSib = l5;
    l5->firstChild = NULL;
    l5->rightSib = NULL;
    l6->firstChild = NULL;
    l6->rightSib = NULL;
    LastGeneration(l1);
    return 0;
}
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

每天进步一点丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值