目录
一、二叉树是?
1.建树(先序pre 中序in 后序post)
数据结构:pair<int,int> tree[N];
①特判
if(la>ra || lb>rb) return 0;
②先在中序找到你当前树的根
int p=la; while(in[p]!=pre[lb]) p++
当前树指的是你的当前树,之后进入子树,当前树就变成了那个子树。
而这个根已经给出,其实就是你当前树的pre的第一个
③求出左子树的长度
int len = p-la;
④当前根的左孩子和右孩子递归求解
四个参数为:in的第一个索引和最后一个索引 pre的第一个索引和最后一个索引
int root=pre[lb]; Tree[root].l=build(la,p-1,lb+1,lb+len); Tree[root].r=build(p+1,ra,lb+len+1,rb); return root;
Build代码
int build(int la,int ra,int lb,int rb){//la-ra中序遍历,lb-rb先序遍历 if(la>ra || lb>rb) return 0; int p=la; while(in[p]!=pre[lb]) p++; int len=p-la; int root=pre[lb]; Tree[root].l=build(la,p-1,lb+1,lb+len); Tree[root].r=build(p+1,ra,lb+len+1,rb); return root; }
2.层序遍历BFS
思路:先把根放进去--》按照先右再左的结点顺序push进去
(注意:如果结点左右都为0,就不放,因为是叶子结点)
void bfs(int root){ queue<int> q; q.push(root); while(q.size()){ root=q.front(); q.pop(); ans.push_back(root); int l=Tree[root].l; int r=Tree[root].r; if(r) q.push(r); if(l) q.push(l); } }
二、例题
L2-004 这是二叉搜索树吗?
#include<bits/stdc++.h> using namespace std; const int N=1010; vector<int> ans; int a[N]; void dfs1(int root,int tail){//左小右大 if(root>tail) return; int l=root+1,r=tail; while(a[l]<a[root]&&l<=tail) l++; while(a[r]>=a[root]&&r>root) r--; if(l-r!=1) return; dfs1(root+1,r);//向左子树递归 dfs1(l,tail);//向右子树递归 ans.push_back(a[root]);//存放的是后根遍历的结果 } void dfs2(int root,int tail){//左大右小 if(root>tail) return; int l=root+1,r=tail; while(a[l]>=a[root]&&l<=tail) l++; while(a[r]<a[root]&&r>root) r--; if(l-r!=1) return; dfs2(root+1,r);//向左子树递归 dfs2(l,tail);//向右子树递归 ans.push_back(a[root]);//存放的是后根遍历的结果 } int main() { int n;cin>>n; for(int i=0;i<n;i++) cin>>a[i]; dfs1(0,n-1); if(ans.size()!=n){ ans.clear(); dfs2(0,n-1); } if(ans.size()==n){ cout<<"YES"<<endl; for(int i=0;i<n;i++) cout<<ans[i]<<" \n"[i == n-1]; } else cout<<"NO"<<endl; return 0; }
L2-006 树的遍历
#include<bits/stdc++.h> using namespace std; #define x first #define y second const int N=35; pair<int,int> tree[N]; int post[N],in[N];//后序 中序 int n; int build(int la,int lb,int ra,int rb){//构造二叉树 if(la>lb || ra>rb) return 0; int root=post[rb];//当前根节点为后序遍历的最后一个点 int p=la; while(in[p]!=root) p++; int cnt=p-la; tree[root].x=build(la,p-1,ra,ra+cnt-1);//递归建立当前节点的左右子树 tree[root].y=build(p+1,lb,ra+cnt,rb-1); return root; } void bfs(int root){//层序遍历 queue<int> q; q.push(root); vector<int> ans; while(q.size()){//层序遍历将节点压入ans int t=q.front(); q.pop(); ans.push_back(t); if(tree[t].x) q.push(tree[t].x); if(tree[t].y) q.push(tree[t].y); } for(int i=0;i<ans.size();i++){ if(!i) cout<<ans[i]; else cout<<" "<<ans[i]; } } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>post[i]; for(int i=1;i<=n;i++) cin>>in[i]; int root=build(1,n,1,n); bfs(root); return 0; }
L2-011 玩转二叉树
#include<bits/stdc++.h> using namespace std; #define l first #define r second const int N=110; int in[N],pre[N]; pair<int,int> tree[N]; vector<int> ans; int build(int la,int ra,int lb,int rb){//la-ra中序遍历,lb-rb先序遍历 if(la>ra || lb>rb) return 0; int p=la; int root=pre[lb]; while(in[p]!=root) p++; int len=p-la; tree[root].l=build(la,p-1,lb+1,lb+len); tree[root].r=build(p+1,ra,lb+len+1,rb); return root; } void bfs(int root){ queue<int> q; q.push(root); while(q.size()){ root=q.front(); q.pop(); ans.push_back(root); int l=tree[root].l; int r=tree[root].r; if(r) q.push(r);//先存右再存左(相当于交换) if(l) q.push(l); } } int main() { int n;cin>>n; for(int i=1;i<=n;i++) cin>>in[i]; for(int i=1;i<=n;i++) cin>>pre[i]; build(1,n,1,n); bfs(pre[1]); for(int i=0;i<ans.size();i++){ cout<<ans[i]; if(i!=ans.size()-1) cout<<" "; } return 0; }