版权声明:我的GitHub:https://github.com/617076674。真诚求星! https://blog.csdn.net/qq_41231926/article/details/83573016
我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED
原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805485033603072
题目描述:
题目翻译:
1020 树的遍历
假设二叉树节点上的所有值都是不同的正整数。给你一棵二叉树的后序遍历和中序遍历结果,你需要给出其层序遍历结果。
输入格式:
每个输入文件包含一个测试用例。在每个测试用例中,第一行给出一个正整数N(<= 30),代表二叉树的节点个数。第二行给出后序遍历结果,第三行给出中序遍历结果。一行中所有的数字由一个空格分隔。
输出格式:
对每个测试用例,在一行中打印出这课二叉树的层序遍历结果。一行中所有的数字必须以一个空格分隔,行末不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
知识点:二叉树的后序遍历、层序遍历、中序遍历
思路一:指针实现
中序遍历可以与前序遍历、后序遍历、层序遍历中的任意一来构建一棵唯一的二叉树,而后三者两两搭配或是三个一起上都无法构建唯一的二叉树。原因是前序、后序、层序均是提供根节点,作用是相同的,都必须由中序遍历来区分出左右子树。
时间复杂度与这课二叉树的构成有关,最坏情况是退化成一个链表,是O(N)的复杂度,最好情况是一颗平衡二叉树,是O(logN)的复杂度。空间复杂度是O(N)。
C++代码:
#include<iostream>
#include<queue>
using namespace std;
struct node {
int data;
node* lchild;
node* rchild;
};
int N; //二叉树的节点个数
int postOrder[31]; //后序遍历数组
int inOrder[31]; //中序遍历数组
int levelOrder[31];
int index = 0;
/*
当前后序序列区间为[leftPost, rightPost],中序序列区间为[leftIn, rightIn],返回根节点地址
*/
node* create(int leftPost, int rightPost, int leftIn, int rightIn);
/*
层序遍历二叉树
*/
void levelTraversal(node* root);
int main(){
cin >> N;
for(int i = 0; i < N; i++){
cin >> postOrder[i];
}
for(int i = 0; i < N; i++){
cin >> inOrder[i];
}
node* root = create(0, N - 1, 0, N - 1); //这里右边界是N - 1,而不是N,在函数的定义中,左右边界都是闭区间
levelTraversal(root);
for(int i = 0; i < N; i++){
cout << levelOrder[i];
if(i != N - 1){
cout << " ";
}
}
cout << endl;
return 0;
}
node* create(int leftPost, int rightPost, int leftIn, int rightIn){
if(leftPost > rightPost){
return NULL; //后序序列的长度小于等于0时,直接返回
}
node* root = new node;
root->data = postOrder[rightPost]; //新节点的数据域为根结点的值
int k;
for(k = leftIn; k <= rightIn; k++){
if(inOrder[k] == postOrder[rightPost]){
break;
}
}
int numLeft = k - leftIn; //左子树的节点个数
root->lchild = create(leftPost, leftPost + numLeft - 1, leftIn, k - 1);
root->rchild = create(leftPost + numLeft, rightPost - 1, k + 1, rightIn);
return root;
}
void levelTraversal(node* root){
if(root == NULL){
return;
}
queue<node*> q;
q.push(root);
while(!q.empty()){
node* now = q.front();
q.pop();
levelOrder[index++] = now->data;
if(now->lchild != NULL){
q.push(now->lchild);
}
if(now->rchild != NULL){
q.push(now->rchild);
}
}
}
C++解题报告:
思路二:静态数组实现
建立一个大小为节点上限个数的node型数组,所有动态生成的节点都直接使用数组中的节点,所有对指针的操作都改为对数组下标的访问。
C++代码:
#include<iostream>
#include<queue>
using namespace std;
struct node {
int data;
int lchild;
int rchild;
};
int N; //二叉树的节点个数
int postOrder[31]; //后序遍历数组
int inOrder[31]; //中序遍历数组
int levelOrder[31]; //层序遍历数组
node Node[31];
int index = 0;
int resultIndex = 0;
int create(int leftPost, int rightPost, int leftIn, int rightIn);
void levelTraversal(int root);
int main(){
cin >> N;
for(int i = 0; i < N; i++){
cin >> postOrder[i];
}
for(int i = 0; i < N; i++){
cin >> inOrder[i];
}
int root = create(0, N - 1, 0, N - 1);
levelTraversal(root);
for(int i = 0; i < N; i++){
cout << levelOrder[i];
if(i != N - 1){
cout << " ";
}
}
cout << endl;
return 0;
}
int create(int leftPost, int rightPost, int leftIn, int rightIn){
if(leftPost > rightPost){
return -1;
}
int root = index++;
Node[root].data = postOrder[rightPost];
int k;
for(k = leftIn; k <= rightIn; k++){
if(inOrder[k] == postOrder[rightPost]){
break;
}
}
int numLeft = k - leftIn;
Node[root].lchild = create(leftPost, leftPost + numLeft - 1, leftIn, k - 1);
Node[root].rchild = create(leftPost + numLeft, rightPost - 1, k + 1, rightIn);
return root ;
}
void levelTraversal(int root){
if(root == -1){
return;
}
queue<int> q;
q.push(root);
while(!q.empty()){
int now = q.front();
q.pop();
levelOrder[resultIndex++] = Node[now].data;
if(Node[now].lchild != -1){
q.push(Node[now].lchild);
}
if(Node[now].rchild != -1){
q.push(Node[now].rchild);
}
}
}
C++解题报告: