本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。
输入格式:
第一行给出正整数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<iostream>
#include<algorithm>
using namespace std;
typedef struct Node{
int Data;
Node *LChild;
Node *RChild;
}BiTNode,*BiTree;
const int N = 1e5 + 10;
int in[N],post[N],n;
/*
因为当同时知道 先序结果 + 中序结果 或者 后序结果 + 中序结果 就可以唯一确定一颗二叉树,所以可以利用所给出的数据进行二叉树的重建
首先要知道的是后序遍历和中序遍历的特点
后序:左子树 右子树 根节点
中序:左子树 根节点 右子树
Tips: 同一棵树它的各种遍历顺序出来的结果的长度都是一样的
模拟一下建树的过程:
后序:2 3 1 5 7 6 4
中序:1 2 3 4 5 6 7
由最初始的后序可知这棵树的根节点是 4 同时,由中序遍历可知 根节点 的左子树为 1 2 3 (长度为 3) 构成的集合 右子树为 5 6 7 (长度也为 3) 构成的集合
再看后序遍历 前面长度为3的集合即为根节点左子树的后序遍历的结果,紧跟着的剩下的元素就是根节点右子树后序遍历的结果,可知左子树的根节点为1,右子
树的根节点为 6 ,再次回到中序遍历中去,可知 1 无左子树,所以由 2 和 3 构成的集合是 1 的右子树,而 6 的左子树为 5,右子树为 7,回到后序中去看,
则有 集合 2 3 的根节点为 3 ,其左子树为 2.
可得出树为:
4
1 6
# 3 5 7
2 # # # # #
# #
*/
// i 和 j分别为中序和后序数组中的指针,len表示当前的集合中的元素个数
void Create_tree(BiTree *Bt,int i,int j,int len)
{
if(len <= 0) // 该子树不存在,将该子树赋值为NULL,作为不存在的标志
{
(*Bt) = NULL;
return ;
}
int temp = i;// 暂时记录中序数组中指针的初始值
while(in[temp] != post[j + len - 1]) // post[j + len - 1]表示当前的根节点(元素集合中最后一个被遍历的点)
{
temp ++; // 使用中序遍历来确定当前子树的集合元素的个数(长度)
}
(*Bt) = new BiTNode;
(*Bt)->Data = post[j + len - 1]; // 放入当前的根节点
int dist = temp - i; // 获得新的集合长度
Create_tree(&((*Bt)->LChild),i,j,dist); // 继续创建左子树 dist 是左子树的元素集合中元素的个数
Create_tree(&((*Bt)->RChild),temp + 1,j + dist,len - dist - 1); // 继续创建右子树 (len - dist - 1)是右子树的元素集合中元素的个数
}
void Pre(BiTree Bt)
{
if(Bt != NULL)
{
cout << " " << Bt->Data;
Pre(Bt->LChild);
Pre(Bt->RChild);
}
}
int main(void)
{
cin >> n;
for(int i = 1;i <= n;i++) cin >> post[i];
for(int i = 1;i <= n;i++) cin >> in[i];
BiTree Bt = NULL;
Create_tree(&Bt,1,1,n);
cout << "Preorder:";
Pre(Bt);
return 0;
}