给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
根据中序以及后序确定一棵树,再用队列逐层输出
有了后序可以确定根,根据根在中序中的位置可以将树划分为左子树以及右子树,迭代即可。
#include<iostream>
using namespace std;
#include<queue>
int *a,*b;
int nodeNum=0;
struct node{
int root;
int left,right;
}node[31];
//后序 中序
int dfs(int a[],int b[],int len){
if(len<=0)
return -1;
int index=0;//中序集合中 当前父节点的索引
while(b[index]!=a[len-1]){
index++;
}
int rt=nodeNum++;
node[rt].root=b[index];
node[rt].left=dfs(a,b,index);
node[rt].right=dfs(a+index,b+index+1,len-index-1);
return rt;
/*node[nodeNum].root=b[index];
node[nodeNum].left=dfs(a,b,index);
node[nodeNum].right=dfs(a+index,b+index+1,len-index-1);
nodeNum++;
cout<<nodeNum<<endl;
return nodeNum-1;*/
}
void bfs(){
queue<int> q;
q.push(0);
while(!q.empty()){
int cur=q.front();
q.pop();
if(cur!=0)
cout<<" ";
cout<<node[cur].root;
if(node[cur].left!=-1) q.push(node[cur].left);
if(node[cur].right!=-1)q.push(node[cur].right);
}
}
int main(){
int n;
cin>>n;
a=new int[n];
b=new int[n];
for(int i=0;i<n;i++)
cin>>a[i];
for(int i=0;i<n;i++)
cin>>b[i];
dfs(a,b,n);
bfs();
return 0;
}
上述代码中注释部分代码有问题,这里nodeNum不可以直接使用,因为在迭代过程中nodeNum在不断改变,在最后得到nodeNum时已经不是我们所需要的nodeNum了。这里需要对迭代进行一下说明,迭代过程中需要将当前调用的函数进行压栈,而此时你的node【nodeNum】.left以及right需要依赖调用dfs的返回结果,在dfs调用时nodeNum再次改变。即当前的【nodeNum】你以为是0,其实他已经在调用dfs过程中进行改变,那他的结果是什么就取决于你的终点nodeNum(最后一次调用即就是迭代的退出那一次之前)。因此我们需要使用一个临时变量来进行存储nodeNum的当前值。所以在迭代过程时需要谨慎使用全局变量。
再对整个dfs函数进行解释:
a是后序 b是中序
a是数组,b也是数组
node[rt].root=b[index];
我们可以通过上面的建树知道建树过程就是一个循环所以我们
只需要传入每次需要的数组元素起点,至于终点我们可以根据len来确定
这样就将两个大的数组转化为两个小的数组来进行建树,分而治之。
node[rt].left=dfs(a,b,index);
左边我们只需要数组的起点就可
我们通过一个循环可以在中序数组
中找到根的索引index,这个index是相较每一次数组的起点,
所以它也代表长度。
node[rt].right=dfs(a+index,b+index+1,len-index-1);
注意这里数组起始点都是0 而不是1
右边我们需要做一点变化得到数组起点 我们知道index代表长度,那么后序数组
新起点就是减去左子树元素后的剩余元素的起点 就是后序数组跨过index个长度
中序数组不但需要减去左子树元素 还有一个根元素 所以需要跨过index+1个长度
那么剩下数组的长度=右子树元素个数 总长len-中序数组跨过的长度(index+1)
可以通过下面的方式来理解上面的说法
这里我们使用的存放后序中序的数组是全局变量我们亦可以通过直接使用起点终点来避免计算len 等出错
int dfs(int abegin,int aend,int bbegin,int bend){
if(aend-abegin==0)
return -1;
int index=0;//中序集合中 当前父节点的索引
while(b[index]!=a[aend]){
index++;
}
int rt=nodeNum++;
node[rt].root=b[index];
node[rt].left=dfs(abegin,abegin+index-1,bbegin,bbegin+index-1);
node[rt].right=dfs(a+index,aend-1,b+index+1,bend);
return rt;
}