这道题的思路是先构建二叉树,然后层序遍历二叉树。将问题拆解:1.如何构建二叉树。2.如何测层序遍历二叉树。
1.构建二叉树
首先我们要知道一棵二叉树可由它的中序遍历和后序遍历确定:
(1)后序遍历的最后是该树或子树的根
(2)中序遍历根的左右分左子树和右子树
通过后序遍历找到根的值,然后再到中序序列里找到根的位置再将该树分为左子树与右子树 。不断递归即可通过中序和后序重塑一棵树。
int build(int il,int ir,int pl,int pr)//il,ir为中序遍历的左右下标;pl,pr为后序遍历的下标 { int root=postorder[pr]; //后序遍历的最后一位是树的根 int k=pos[root];//pos数组记录了每个数的下标 //根将中序遍历分成两部分,分别是左子树、右子树 //l,r 为map,记录左右子树。 if(il<k) l[root]=build(il,k-1,pl,k-1-il+pl);//k-1-il=x-pl //左子树在中序序列中为[il,k-1] ,在后序序列中左子树长度相同,从pl开始,故 x-pl=k-1-il,x即右端点为k-1-il+pl; if(k<ir) r[root]=build(k+1,ir,pr-ir+k,pr-1);// pr-1-x=ir-k-1 //右子树在中序序列中为[k+1,ir] ,在后序序列中右子树长度相同,到pr-1结束,故 pr-1-x=ir-k-1,x即左端点为pr-ir+k; return root; }
2.bfs层序遍历树
void bfs(int root) { queue<int> q; q.push(root); int flag=1;//标记是否第一次输出,第一次输出数组,后续输出空格数字;为了最后数字没有输出空格(pat格式要求) while(q.size()){ int x=q.front(); q.pop(); if(flag){ cout<<x; flag=0; } else cout<<" "<<x; if(l.count(x)) q.push(l[x]);//如果左节点在,则放入队列 if(r.count(x)) q.push(r[x]);//如果有右节点,则放入队列 } }
整体代码:
#include<iostream> #include<algorithm> #include<string> #include<unordered_map> #include<queue> using namespace std; const int N=40; int postorder[N],inorder[N]; unordered_map<int,int> l,r,pos; int build(int il,int ir,int pl,int pr) { int root=postorder[pr]; int k=pos[root]; if(il<k) l[root]=build(il,k-1,pl,k-1-il+pl);//k-1-il=x-pl if(k<ir) r[root]=build(k+1,ir,pr-ir+k,pr-1);// pr-1-x=ir-k-1 return root; } void bfs(int root) { queue<int> q; q.push(root); int flag=1; while(q.size()){ int x=q.front(); q.pop(); if(flag){ cout<<x; flag=0; } else cout<<" "<<x; if(l.count(x)) q.push(l[x]); if(r.count(x)) q.push(r[x]); } } int main() { int n; cin>>n; for(int i=0;i<n;i++) cin>>postorder[i]; for(int i=0;i<n;i++){ cin>>inorder[i]; pos[inorder[i]]=i;//pos存放每个数的下标 } int root=build(0,n-1,0,n-1);//构建二叉树 bfs(root);//层序遍历 return 0; }