AcWing 1497. 树的遍历
原题链接
简单
作者:
清_1
,
2021-04-10 23:02:48
,
所有人可见
,
阅读 505
算法1
思路:设置一个哈希表存左儿子,右儿子,和每个节点的位置,一共涉及两个函数,一个函数用来建立二叉树,一个函数用来遍历左右子树,这个题有一点需要注意的就是后序遍历的左右子的确定
关于build函数:传入中序遍历和后序遍历的左右边界,令根节点等于后序遍历的右边界,也就是最后一个数,k记录根节点的位置,分别对左右子树进行递归
关于bfs函数:这个函数让树先序输出出来,定义一个队列,将根节点存进去,q存在时候,弹出的队头节点输出,因为先序遍历是根左右,然后判断左右子树是否存在,如果存在,push到队列
C++ 代码
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<queue>
using namespace std;
const int N=40;
int n;
int postorder[N],inordered[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];//用k存根节点的下标
//如果左子树存在,遍历左子树
//这里比较好确定中序的左右边界,设后序遍历的右边界为x,x-pl=ir-il,解方程
if(il<k) l[root]=build(il,k-1,pl,pl+k-il-1);
//如果右子树存在
if(ir>k) r[root]=build(k+1,ir,pl+k-il+1-1,pr-1);
return root;
}
void bfs(int root)
{
queue<int> q;
q.push(root);//将根节点入队
while(q.size())
{
auto t=q.front();//将队头元素取出并删除
q.pop();
cout<<t<<' ';
//如果左子树存在,将节点插入左子树队列里,同理右边
if(l.count(t))q.push(l[t]);
if(r.count(t))q.push(r[t]);
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)cin>>postorder[i];
for(int i=0;i<n;i++)
{
cin>>inordered[i];
pos[inordered[i]]=i;//存一下中序遍历每个点下标是多少
}
int root=build(0,n-1,0,n-1);//递归构建二叉树
bfs(root);
return 0;
}