PTA习题:根据后序和中序遍历输出先序遍历(用C++编写)

给一个PTA题目链接
由于个人学业不得不做一些PTA作业,突然发现这道PTA题比较经典,于是打算写篇博客来记录一下,写的不好请多多担待QAQ。

题目描述:

本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。

输入格式:

第一行给出正整数N(≤30),是树中结点的个数。随后两行,每行给出N个整数,分别对应后序遍历和中序遍历结果,数字间以空格分隔。题目保证输入正确对应一棵二叉树。

输出格式:

在一行中输出Preorder:以及该树的先序遍历结果。数字间有1个空格,行末不得有多余空格。

输入样例:

7

2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例:

Preorder: 4 1 3 2 6 5 7

题解:

先贴代码:

#include<bits/stdc++.h>
#define mset(addr,num) memset(addr,num,sizeof(addr))
#define all(temp) temp.begin(),temp.end()
#define PP p3air< int , int > 
typedef long long ll;
const long double PI = acos(-1.0);
const ll llINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
using namespace std;
const int maxn=2e5+7,maxm=1e6+7;
int N,M,K; 
int data1[107], data2[107];

struct TNode{
    
    
	int val=-1;
	TNode* ltree=NULL;
	TNode* rtree=NULL;
};

void slove(TNode* now, int low1, int hei1, int low2, int hei2){
    
     
//用两对变量分别表示当前子树的后序遍历区间和中序遍历区间
	if(low2 == hei2)return;
	now->ltree  = new TNode;
	now->rtree  = new TNode;
	now->val = data1[hei1-1];
	int i;
	for(i=low2; i<hei2; ++i)
		if(data2[i] == data1[hei1-1])break; //找到根节点的值
	
	//递归传参
	slove(now->ltree, low1, low1-low2+i, low2, i); //进入左子树
	slove(now->rtree, low1-low2+i, hei1-1, i+1, hei2); //进入右子树
}

void Tprint(TNode* now){
    
    
	cout<<" "<<now->val;
	if(now->ltree->val  != -1)Tprint(now->ltree);
	if(now->rtree->val  != -1)Tprint(now->rtree);
	return;
}

int main() {
    
    
	ios::sync_with_stdio(false); cin.tie(0);
	TNode* root = new TNode;
	int n;
	cin>>n;
	for(int i=0; i<n; ++i)cin>>data1[i];
	for(int i=0; i<n; ++i)cin>>data2[i];
	slove(root, 0, n, 0, n);
	cout<<"Preorder:";
	Tprint(root);
	
	return 0;
}

说明:前面的那些宏定义可以不管,只是为了写题时方便,现在懒得删了;数据是开在全局里面的,方便编写;采取动态建树。

好了,开始讲解

  1. 首先根据当前子树的后序遍历结果得出当前子树的根节点–即该遍历结果的最后一个元素;
  2. 在当前子树的中序遍历结果中得出其左子树与右子树的中序遍历结果–这里用两个变量来记录首尾区间,详见代码;
  3. 在当前子树的后序遍历结果中得出其左子树与右子树的后序遍历结果–这里用两个变量来记录首尾区间(注意,二三步的区间采取左闭右开表示,并且已被算出,见代码中递归传参那一步);
  4. 递归进入左右子树;
  5. 重复1-4的步骤,直至完全遍历。
  6. 输出结果,搞定!

核心思想其实就是根据一个树的后序遍历结果得出树的根节点,再利用该树的中序遍历结果得出左右子树的后序遍历结果,然后递归下去。

细节

其实没什么细节,这道题也不算难题,就是给子树传位置的时候注意下就行了;另外,区间是用左闭右开表示的,其他没什么坑点。

最后推广下博客:https://gh.sanqii.top

猜你喜欢

转载自blog.csdn.net/San__Qi/article/details/102737373