今天做PAT的时候,发现有几道题是关于先序/中序或后序/中序构建二叉树的,特此处总结分析,以便后序复习:
我这边以根据后序和中序来得出层次遍历的序列为例分析:
基本思想:
1、根据后序序列最后一个元素找到根节点
2、根据这个根节点在中序序列中找到该根节点,刚好把序列分成左子树和右子树
3、递归调用,即可构建二叉树
然后再根据需要输出先序遍历、后序遍历、中序遍历或者层次遍历
具体例子的理解可以参考代码上面的注释
练习题可参考浙大PAT的1020. Tree Traversals (25)
AC的参考代码:
#include <iostream>
#include <queue>
using namespace std;
struct Node { //定义二叉树节点
int value;
Node *leftLeaf;
Node *rightLeaf;
};
int N;
int isTree = 1; //用来判断能否构成二叉树
Node *builtTree(int *post,int *in,int length){ //根据中序和后序序列建立二叉树
Node *root = new Node();
root->value = post[length-1];
root->leftLeaf = NULL;
root->rightLeaf = NULL;
int index;
for(index=0;index<length;index++){ //找根节点的位置
if(in[index]==root->value)
break;
}
if(index>=length){ //没在合适的范围内找到根节点,无法构建树
isTree = 0;
return NULL;
}
if(index>0){ //存在左子树
root->leftLeaf = builtTree(post,in,index); //参数:post起始点,in起始点,数组长度
}
if(length-index-1>0){ //存在右子树
root->rightLeaf = builtTree(post+index,in+index+1,length-index-1);
}
return root;
}
void printLevel(Node *root){ //输出层次遍历序列
int countTotal = 1;
queue<Node> qu; //层次遍历用队列实现
qu.push((*root));
while(!qu.empty()){
Node temp = qu.front();
qu.pop();
countTotal<N?cout<<temp.value<<" ":cout<<temp.value; //去掉最后的那个空格
countTotal++;
if(temp.leftLeaf!=NULL){
qu.push(*temp.leftLeaf);
}
if(temp.rightLeaf!=NULL){
qu.push(*temp.rightLeaf);
}
}
}
int main()
{
cin>>N;
int post[N];
int in[N];
for(int i=0;i<N;i++){
cin>>post[i];
}
for(int i=0;i<N;i++){
cin>>in[i];
}
Node *root = builtTree(post,in,N);
printLevel(root);
return 0;
}