开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 18 天,点击查看活动详情
分析
之前写的东西比较rubblish,现在重新写一下递归这玩意我只能说学的依托答辩,怎么办捏,啃吧在写这题之前我感觉我对数据结构一无所知,就比如树的前中后序遍历,然后这题顺便学了下,树的前序遍历就是树的bfs序,按照根节点 -> 左儿子 -> 右儿子顺序遍历一棵树然后输出,中序遍历应该是最难理解的,但是也就正如字面意思,遍历的顺序是左儿子 -> 根节点 -> 右儿子,那么后序遍历显然就是左儿子 -> 右儿子 -> 根节点,然后还有个特点,就是后续遍历的最后一个编号是根节点编号,在中序遍历里面对应的点为分界线,左边是左子树,右边是右子树,然后后续遍历就几记好了出现在一颗子树最右端的编号就是这颗子树的根节点,然后根据这些我们可以先建立这颗二叉树,建立完了之后bfs就可以输出前序遍历了。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
#include <cmath>
#include <unordered_map>
#include <stack>
#include <queue>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
typedef pair<int,int> PII;
typedef pair<string,int> PSI;
typedef stack<int> stk;
int gcd(int x,int y){return y?gcd(y,x%y):x;}
ll qmi(ll x,ll y,int mod){
ll res=1;
while(y){if(y&1) res=res*x%mod;y>>=1;x=x*x%mod;}
return res;
}
const int N=40;
unordered_map<int,int> l,r,pos;
//l记录左子树,r记录右子树,pos记录中序遍历中编号的下标
int postorder[N],inorder[N],n;
//postorder记录后序遍历,inorder记录中序遍历。
int build(int il,int ir,int pl,int pr){
//建树的过程(il和ir是中序遍历,pl和pr是后后序遍历)
//这个返回的是根节点
int root=postorder[pr];
//后序遍历的最后一个编号是(子树)根节点编号,就是pr
int k=pos[root];
//这里找出根节点编号在后续遍历中的位置(哈希值)
if(il<k) l[root]=build(il,k-1,pl,k-1-il+pl);
//如果中序遍历的左边小于根节点,那么就可以递归建立
//左子树
if(k<ir) r[root]=build(k+1,ir,k-il+pl,pr-1);
//如果中序遍历的右边大于根节点,那么就可以递归建立
//右子树
return root;
}
inline void bfs(int root){
queue<int> q;
q.push(root);
while(q.size()){//前序遍历就是输出二叉树的bfs序,
//先看这根点左边有没有儿子,有的话就入队,再看右边
//有没有儿子,有的话就入队
int t=q.front();
//将对头输出(bfs序)
cout<<t<<" ";
q.pop();
if(l.count(t)) q.push(l[t]);
if(r.count(t)) q.push(r[t]);
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
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;//将中序遍历记录下来
}
int root=build(0,n-1,0,n-1);//建树
bfs(root);//bfs输出
return 0;
}
}
希望能帮助到大家