由中序遍历与后序遍历确定一棵二叉树

1. 问题描述:

题目来自于PAT A 1020,具体描述如下:

Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

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

Sample Output:

4 1 6 3 5 7 2

题目的大概意思是:给出一棵二叉树的后序遍历序列和中序遍历序列,求出这颗二叉树的层次遍历序列

样例解释:使用给定的后序序列与中序序列可以构建出下面的二叉树:

 由中序遍历与后序遍历确定一棵二叉树_第1张图片

2. 思路分析:

① 中序遍历可以与前序遍历、后序遍历和层次遍历中的任意一个来构建唯一的二叉树,而后三者两两搭配或者是三个一起上都无法创建一颗唯一的一颗二叉树,原因是先序、后序、层次遍历均是提供根节点,作用是相同的,都必须由中序遍历来区分出左子树与右子树,所以中序遍历与后序遍历可以唯一确定一棵二叉树

② 首先是要先确定二叉树的根,确定二叉树的根可以在二叉树的后序遍历序列中去找,后序遍历中最后一个节点就是根节点,然后再在中序遍历中找到根节点区分出左子树与右子树

假设递归过程中某步的后序序列区间是[postL, postR],中序序列区间为[inL, inR],那么由后序序列的性质可以知道,后序序列的最后一个元素post[postR]即为根节点,接着需要在中序序列中寻找一个位置k,使得in[k] == post[postR],这样就找到了中序序列中的根节点,易知左子树结点个数为numLeft = k - inL;于是左子树的后序序列区间为[postL,postL + numLeft - 1],左子树的中序序列区间是[inL,k - 1],右子树的后序序列区间是[postL + numLeft],右子树的中序序列区间为[k + 1,inR]

注意点:输出的时候需要注意控制最后一个数后面的空格不应该被输出

3. 下面是具体的C++代码:

#include
#include
#include
#include
using namespace std;
const int maxn = 50;
struct node{
	int data;
	node *left;
	node *right;
}; 
int in[maxn], post[maxn];
int n;
//当前二叉树的后序遍历区间是[postL, postR], 中序遍历的区间是[inL, inR]
//create函数返回构建出的二叉树的根节点地址 
node *create(int postL, int postR, int inL, int inR){
	if(postL > postR) return NULL;
	node *root = new node();
	//新节点的数据域为根节点的值 
	root->data = post[postR];
	int k;
	for(k = inL; k <= inR; k++){
		if(in[k] == post[postR]) break;
	}  
	//左子树中根节点的个数 
	int numLeft = k - inL;
	//返回左子树中根节点的地址,赋值给root的左指针
	root->left = create(postL, postL + numLeft - 1, inL, k - 1);
	//返回右子树中根节点的地址,赋值给root的右指针
	root->right = create(postL + numLeft, postR - 1, k + 1, inR);
	return root; 
}

int num = 0;
//层次遍历 
void bfs(node *root){
	queue q;
	q.push(root);
	while(!q.empty()){
		node *now = q.front();
		q.pop();
		printf("%d", now->data);
		num++;
		if(num < n) printf(" ");
		if(now->left != NULL) q.push(now->left);
		if(now->right != NULL) q.push(now->right);
	} 
}

int main(void){
	scanf("%d", &n);
	for(int i = 0; i < n; i++){
		scanf("%d", &post[i]);
	}
	for(int i = 0; i < n; i++){
		scanf("%d", &in[i]);
	}
	node *root = create(0, n - 1, 0, n - 1);
	bfs(root);
	return 0;
} 

 

你可能感兴趣的:(树,C&&C++)