7-3 根据后序和中序遍历输出先序遍历 (25分)

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

输入格式:
第一行给出正整数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
#include

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;
}

你可能感兴趣的:(PTA)