注:此题是一道二叉树的构建+递归+BFS的综合应用题,值得新手好好学习一番!
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.
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.
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.
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
4 1 6 3 5 7 2
已知后序和中序,求层序!
可以先来理解一下一个模板:
模板解决了已知先序和中序,重建二叉树的问题!遇到这种题,如果不会熟练,建议先画个图,在图中分析!
//一个已知先序和中序,重建二叉树的例子
node* create(int preL,int preR,int inL,int inR)
{
//递归边界
if(preL>preR)
{
return NULL;//先序序列长度小于等于0时,直接返回
}
node* root=new node; //新建一个新的节点,用来存放当前二叉树的根节点
root->data=pre[preL];//新结点的数据域为根节点的值
int k;
//找出当前子树的中序序列中根节点的下标k
for(k=inL;k<=inR;k++)
{
if(in[k]==pre[preL])//在中序序列中找到ink[k]==pre[L]的节点
break;
}
int numLeft=k-inL;//左子树的节点个数
//左子树的先序区间[preL+1,preL+numLeft],中序区间为[inL,k-1]
//返回左子树的根节点地址,赋值给root的左指针
root->lchild=create(preL+1,preL+numLeft,inL,k-1);
//右子树的先序区间[preL+numLeft+1,preR],中序区间为[k+1,inR]
//返回右子树的根节点 ,赋值给root的右指针
root->rchild=create(preL+numLeft+1,preR,k+1,inR);
return root;
}
解题思路:
一般解法,重建二叉树,再BFS输出层序遍历的结果。
解答代码:
#include
#include
#include
#include
using namespace std;
const int maxn=50;
struct node{
int data;
node* lchild;
node* rchild;
};
int pre[maxn],in[maxn],post[maxn];
int n; //结点个数
//create函数返回构建出的二叉树的根节点的地址
node* create(int postL,int postR,int inL,int inR)
{
//递归边界
if(postL>postR)
{
return NULL;//后序序列长度小于等于0时,直接返回
}
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->lchild=create(postL,postL+numLeft-1,inL,k-1);
root->rchild=create(postL+numLeft,postR-1,k+1,inR);
return root;
}
int num=0;
void BFS(node* root)
{
queue q;//定义一个node类型的队列
q.push(root);//根节点地址入队
while(!q.empty())
{
node* now=q.front();//取出队首元素
q.pop();
printf("%d",now->data);//访问队首元素
num++;
if(numlchild !=NULL) q.push(now->lchild);//左子树非空
if(now->rchild!=NULL) q.push(now->rchild);//右子树非空
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i
此处还有一种非常规的做法,但可以使代码简洁高效:
为每个节点加一个index,其左子树的根节点索引为2*index+1,右子树的根节点索引为2*index+2,把所有结点放到一个vector中,然后用sort()从小到达排序,然后输出,就得到了层序遍历序列,省去了重建二叉树和BFS层序遍历。
解答代码:
#include
#include
#include
using namespace std;
struct node{
int index;
int value;
};
//用于将vector中的结点从小到达排序的函数
bool cmp(node a,node b)
{
return a.index post,in;
vector ans;
void pre(int postL,int postR,int inL,int inR,int index)
{
if(postL>postR)
return;
int k;
for(k=inL;k<=inR;k++)
{
if(in[k]==post[postR])
break;
}
ans.push_back({index,in[k]});
int numLeft=k-inL;
pre(postL,postL+numLeft-1,inL,k-1,2*index+1);
pre(postL+numLeft,postR-1,k+1,inR,2*index+2);
}
int main()
{
int n;
scanf("%d",&n);
post.resize(n);
in.resize(n);
for(int i=0;i