PAT-ADVANCED1020——Tree Traversals

版权声明:我的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++解题报告:

猜你喜欢

转载自blog.csdn.net/qq_41231926/article/details/83573016
今日推荐