题意
(原题为英文,这里只介绍题目大意)
给出一棵二叉树的后序遍历序列和中序遍历序列,求这棵二叉树的层序遍历序列(每个结点的值均不相同)。
输入样例
假设有一棵二叉树如下:
对应该树的输入样例如下:
7 //结点个数
2 3 1 5 7 6 4 //后序遍历序列
1 2 3 4 5 6 7 //中序遍历序列
输出样例
4 1 6 3 5 7 2 //层序遍历序列
思路
如果要用后序遍历方法来遍历一棵二叉树,那么总是先访问左子树,再访问右子树,最后才访问根结点,因此根结点一定位于后序遍历序列的最后一位,所以,只要给定后序遍历序列,就能直接找到根结点。但是,如果只给出后序遍历序列,那么我们仅仅能够确定根结点,左右子树是没办法区分开的。要唯一确定一棵二叉树,还需要给定中序遍历序列。
对于中序遍历来说,总是先访问左子树,再访问根接点,最后访问右子树。因此,在二叉树的每一个结点数值均不同的情况下,只要遍历中序遍历序列,找到与后序遍历序列的最后一位(即根结点)数值相同的结点,就可以确定该结点为根结点,进而在中序遍历序列中区分出左子树和右子树。
代码
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 100;
struct node
{
int data;
node* ltree;
node* rtree;
};
int mid[maxn], pos[maxn]; //分别存储中序、后序序列的数据
//通过后序序列和中序序列构建二叉树,并返回根节点地址
node* create(int pos_l, int pos_r, int mid_l, int mid_r)
{
if(pos_l > pos_r)
{
return NULL;
}
node* root = new node;
root->data = pos[pos_r];
int k;
for(k = mid_l; k <= mid_r; k++ )
{
if(mid[k] == root->data)
break;
}
int num_l = k - mid_l;
int num_r = mid_r - k;
//递归创建左子树
root->ltree = create( pos_l, pos_l + num_l - 1, mid_l, k - 1 );
//递归创建右子树
root->rtree = create(pos_l + num_l, pos_r - 1, k + 1, mid_r );
return root;
}
int n, num = 0; //通过num控制结尾不输出空格
//层序遍历,采用的是广度优先探索的方法
void BFS(node* root)
{
queue<node*> q;
q.push(root);
while(!q.empty())
{
node* tmp_node = q.front();
cout<<tmp_node->data;
num++;
if(num < n)
cout<<" ";
q.pop();
if(tmp_node -> ltree != NULL)
q.push(tmp_node->ltree);
if(tmp_node -> rtree != NULL)
q.push(tmp_node->rtree);
}
}
int main()
{
cin>>n;
for(int i = 0; i < n; i++)
{
cin>>pos[i];
}
for(int i = 0; i < n; i++)
{
cin>>mid[i];
}
node* root = create(0, n-1, 0, n-1);
BFS(root);
return 0;
}