直接进入正题:
比如有些题目给你一颗二叉树的前序遍历和中序遍历,然后让你求层序遍历或者后序遍历。
这种题目的基本思路有两个:
1.给定的序列是以字符串的形式:
比如后序序列:BDCA,中序序列:BADC ,然后让你求先序序列。
这类问题实际上已经为你构建好了数,只需要利用字符串的截取操作(sunstr)以及dfs / bfs解决:
参考文章<==戳这
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
==>要注意在树的每一部分,任何类型的遍历序列长度都是一样的
void dfs(string mid,string post){
if(mid.empty()) return; ==>序列为空是递归结束的标志
else{
char root=post[post.size()-1]; ==>找到该部分的“主根”
int pos=mid.find(root); ==>“主根”在中序序列中的位置
printf("%c",root); ==>“根”
dfs(mid.substr(0,pos),post.substr(0,pos)); ==>“左”
dfs(mid.substr(pos+1),post.substr(pos,post.size()-k-1)); ==>“右”
}
}
int main(){
string mid,post; ==>中序序列,后序序列
cin>>mid>>post;
dfs(mid,post);
}
2.给定的序列是整形,需要数组存储:
后序序列:2 3 1 5 7 6 4
中序序列:1 2 3 4 5 6 7
然后让你求前序序列。这类问题需要构建这颗二叉树,然后再根据题意运用 dfs / bfs 解决。
比如这道题:求层序序列 就运用了bfs
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
int post[50],inor[50],n; //后序序列,中序序列,个数
struct node{
int date; //结点数据域(结点标号)
node* lchild; //左子树
node* rchild; //右子树
};
node* tree(int postl,int postr,int inl,int inr){ //后序序列的左下标,右下标,中序序列的左下标,右下标
if(postl>postr) return NULL; //如果后序序列小于 1 的时候,到达递归边界
node* root=new node; //创建一个新的结点用来存放根节点
root->date=post[postr]; //后序序列的最后一个元素是根
int k; //找出根节点在中序遍历中的位置并记录
for(k=inl;k<=inr;k++){
if(post[postr]==inor[k]){
break;
}
}
int numleft=k-inl; //左子树的结点个数
//二叉树结点的建立是从左到右的
//更改下标继续建树(仔细)
root->lchild = tree(postl,postl+numleft-1,inl,k-1);
root->rchild = tree(postl+numleft,postr-1,k+1,inr);
return root;
}
int num=0;
void bfs(node* root){ //bfs板子,因为层序遍历本质上就是广搜
queue<node*> q; //注意队列元素类型是 node*
q.push(root);
while(!q.empty()){
node* top=q.front();
q.pop();
printf("%d",top->date); //依次把根节点输出就行了
num++;
if(num<n) putchar(' '); //空格的处理
if(top->lchild!=NULL) q.push(top->lchild);
if(top->rchild!=NULL) q.push(top->rchild);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&post[i]);
for(int i=1;i<=n;i++) scanf("%d",&inor[i]);
node* root=tree(1,n,1,n); //建立以root为根的 node* 类型的一颗二叉树
bfs(root); //bfs层序遍历这颗树
}