给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
思路
按照一般的思路,首先应该想办法根据后序遍历序列post和中序遍历序列in把二叉树构造出来
选择用二叉链表作为树的存储结构,定义如下
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
}Tree;
构造二叉树的第一步是要找到根节点root,就是后序遍历序列的最后一个元素post[n-1]
需要在中序遍历序列中找到根节点的位置,然后再分别递归构造左子树和右子树
BuildTree函数中的参数依次表示的是后序遍历序列,中序遍历序列和结点个数
Tree* BuildTree(int post[], int in[], int n) {
if (n == 0)
return NULL;
int root = 0;
while (in[root] != post[n - 1])
root++; //找到根节点
Tree* T = (Tree*)malloc(sizeof(Tree));
T->data = in[root];
int m = root;
T->left = BuildTree(post, in, m);
T->right = BuildTree(post + m, in + m + 1, n - m - 1);
return T;
}
至此,已经能够将二叉树构造出来了,接下来就是要层次遍历这课二叉树
以下图这棵二叉树为例,实现利用队列完成层次遍历
根结点A入队,A
队列非空,如果有左右孩子,将其左右孩子依次入队
队头结点A出队,将A的左右孩子BC入队,BC
队头结点B出队,将B的左右孩子DE入队,CDE
队头结点C出队,将C的左右孩子FG入队,DEFG
队头结点D出队,将D的左右孩子HI入队,EFGHI
队头结点E出队,E没有左右孩子,无新元素入队,FGHI
队头结点F出队,将F左右孩子JK入队,GHIJK
队头结点G出队,将G的左孩子L入队,HIJKL
队头结点H出队,H没有左右孩子,无新元素入队,IJKL
队头结点I出队,I没有左右孩子,无新元素入队,JKL
队头结点J出队,J没有左右孩子,无新元素入队,KL
队头结点K出队,K没有左右孩子,无新元素入队,L
队头结点L出队,L没有左右孩子,无新元素入队,此时队空,结束遍历
出队的顺序即为层次遍历的顺序:ABCDEFGHJKL
❗️因为是将出队结点的左右孩子入队,所以在定义队列的时候data类型应该是Tree
typedef struct LinkNode {
Tree* data;
struct LinkNode* next;
}LinkNode;
typedef struct {
LinkNode* front, * rear;
}Queue;
最核心的层次遍历的代码如下
void LevelOrder(Tree* t) {
Queue* q = (Queue*)malloc(sizeof(Queue));
initQueue(q);
enQueue(q, t);
while (q->front != NULL) {
Tree* node = deQueue(q);
printf("%d", node->data);
if (node->left) {
enQueue(q, node->left);
}
if (node->right) {
enQueue(q, node->right);
}
/*为满足题目输出的格式要求,只有队列非空的时候才输出空格
这样输出最后一个出队元素之后就不会有空格啦*/
if (q->front != NULL) {
printf(" ");
}
}
}
最后完整代码如下
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
}Tree;
typedef struct LinkNode {
Tree* data;
struct LinkNode* next;
}LinkNode;
typedef struct {
LinkNode* front, * rear;
}Queue;
void initQueue(Queue* q) {
q->front = q->rear = NULL;
}
void enQueue(Queue* q, Tree* x) {
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
if (q->rear == NULL) {
q->front = q->rear = s;
} else {
q->rear->next = s;
q->rear = s;
}
}
Tree* deQueue(Queue* q) {
if (q->front == NULL)
return NULL;
LinkNode* p = q->front;
Tree* x = p->data;
q->front = p->next;
if (q->front == NULL) {
q->rear = NULL;
}
free(p);
return x;
}
Tree* BuildTree(int post[], int in[], int n) {
if (n == 0)
return NULL;
int root = 0;
while (in[root] != post[n - 1])
root++; //找到根节点
Tree* T = (Tree*)malloc(sizeof(Tree));
T->data = in[root];
int m = root;
T->left = BuildTree(post, in, m);
T->right = BuildTree(post + m, in + m + 1, n - m - 1);
return T;
}
void LevelOrder(Tree* t) {
Queue* q = (Queue*)malloc(sizeof(Queue));
initQueue(q);
enQueue(q, t);
while (q->front != NULL) {
Tree* node = deQueue(q);
printf("%d", node->data);
if (node->left) {
enQueue(q, node->left);
}
if (node->right) {
enQueue(q, node->right);
}
/*为满足题目输出的格式要求,只有队列非空的时候才输出空格
这样输出最后一个出队元素之后就不会有空格啦*/
if (q->front != NULL) {
printf(" ");
}
}
}
int main() {
int n;
scanf("%d", &n);
int post[n], in[n];
for (int i = 0; i < n; ++i) {
scanf("%d", &post[i]);
}
for (int i = 0; i < n; ++i) {
scanf("%d", &in[i]);
}
int postIndex = n - 1;
Tree* t = BuildTree(post, in, n);
LevelOrder(t);
}