题目要求:
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
算法思路:
这道题要求从后序遍历和中序遍历中得到层次遍历的结果。因此,我们第一步先根据提供的后序遍历和中序遍历的结果来构造一棵树,然后编写他的层次遍历算法。
这道题的核心在于找到对应的后序遍历段和中序遍历段。接着我们对该对应序列进行分析,我们知道,后序遍历的最后一个节点代表的当前树的根节点。而找到该节点在中序遍历中的位置,在中序遍历节点的左侧和右侧分别得到当前树的左子树和右子树。分析,当前左子树和右子树在后续遍历中的位置,得到新的对应序列,生成新子树。
代码如下:
node* creat(int postL,int postR,int inL,int inR){
//如果已经遍历完了,那么返回空树
if(postL>postR){
return NULL;
}
node* root = new node;
root->data = postOrder[postR];
int i = inL;
//区分左右子树
for(; i < inR ; i++){
if( inOrder[i] == root->data){
break;
}
}
//如果找到,则该节点左侧为左子树,右侧为右子树 左子树节点为 (i-inL) 个, 右子树节点为 (inR - i)
//且左子树边界 中序遍历[inL,i-1]; 后续遍历为[postL,i-1]
//右子树边界为 中序遍历 [i+1,inR] 后序遍历为[i+1,postR-1]
root->lchild = creat(postL , postL+i-inL-1 , inL , i-1 );
root->rchild = creat(postL+i-inL , postR-1, i+1, inR);
return root;
}
关于层次遍历,我们使用一个队列来完成,每次访问当前节点时,将他的左孩子和右孩子依次入队。当队列不为空时,重复该操作。
//层次遍历
//N为元素的个数,用于控制最后一个空格
void levelOrder(node* root,int N){
int count=0;
if(root == NULL || N == 0){
printf("\n");
return;
}
queue<node*> tree;
tree.push(root);
while(!tree.empty()){
node* temp = tree.front();
tree.pop();
if(count < N-1){
printf("%d ",temp->data);
count++;
}else{
printf("%d\n",temp->data);
}
if(temp->lchild != NULL){
tree.push(temp->lchild);
}
if(temp->rchild != NULL){
tree.push(temp->rchild);
}
}
}
代码展示:
#include <cstdio>
#include <queue>
using namespace std;
struct node{
int data;
node* lchild;
node* rchild;
};
int postOrder[31] = {0};
int inOrder[31] = {0};
node* creat(int postL,int postR,int inL,int inR){
//如果已经遍历完了,那么返回空树
if(postL>postR){
return NULL;
}
node* root = new node;
root->data = postOrder[postR];
int i = inL;
//区分左右子树
for(; i < inR ; i++){
if( inOrder[i] == root->data){
break;
}
}
//如果找到,则该节点左侧为左子树,右侧为右子树 左子树节点为 (i-inL) 个, 右子树节点为 (inR - i)
//且左子树边界 中序遍历[inL,i-1]; 后续遍历为[postL,i-1]
//右子树边界为 中序遍历 [i+1,inR] 后序遍历为[i+1,postR-1]
root->lchild = creat(postL , postL+i-inL-1 , inL , i-1 );
root->rchild = creat(postL+i-inL , postR-1, i+1, inR);
return root;
}
//层次遍历
//N为元素的个数,用于控制最后一个空格
void levelOrder(node* root,int N){
int count=0;
if(root == NULL || N == 0){
printf("\n");
return;
}
queue<node*> tree;
tree.push(root);
while(!tree.empty()){
node* temp = tree.front();
tree.pop();
if(count < N-1){
printf("%d ",temp->data);
count++;
}else{
printf("%d\n",temp->data);
}
if(temp->lchild != NULL){
tree.push(temp->lchild);
}
if(temp->rchild != NULL){
tree.push(temp->rchild);
}
}
}
int main(){
int N;
scanf("%d",&N);
//从0开始存储,到n-1
//读入后序遍历序列
for(int i = 0;i<N;i++){
scanf("%d",&postOrder[i]);
}
//读入中序遍历序列
for(int i = 0;i<N;i++){
scanf("%d",&inOrder[i]);
}
node* root;
root = creat(0,N-1,0,N-1);
levelOrder(root,N);
return 0;
}