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 实现过程
- 首先将根结点入队,然后当front < rear时,将结点出队,即将该层结点全部出队,每出一个结点都要将他的所有孩子入队。
- 出队时,++front,移动队头指针。然后将top++,即模拟入栈操作,此时从栈顶到栈底模拟存放的是该层结点的倒序排列。然后将该结点的所有孩子全部入队。
- 当访问到该层的最后一个结点,即front == last时,将层数level+1,修改last为下一层的最后一个结点,即last = rear。判断当前层数是否为最后一层,如果不为最后一层,那么rear > front,修改count为count = rear - front。
- 循环上述操作,直到遍历完最后一层。然后从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;
}