题记
思路
1.创建结点的结构体
2.根据中序遍历和后序遍历递归地创建二叉树。假设中序遍历当前的树下标为inL,inR,后序遍历当前的树下标是poL,poR。后序遍历最后一个就是根结点,循环中序遍历找到根结点,记录下标为k,中序遍历左边的是左子树,右边的是右子树,得到左子树结点个数为numLeft=k-inL,于是得到当前的树的左子树中序遍历下标范围为[intL,K-1],后序遍历为[poL,poL+numLeft-1],右子树中序遍历下标范围为[k+1,inR],后序遍历下标范围为[poL+numLeft,poR].
3.利用队列层次遍历得到的树
总结:
1.中序序列可以与先序序列,后序序列和层次序列中的任意一个来构建唯一的二叉树,而后三者两两搭配或是三个一起都无法构建唯一的二叉树。原因是后三者均是提供根节点,作用是相同的,都无法区分出左右子树。
2.BFS用的队列的元素是结点指针类型,这道题其实可以只用普通的节点类型就可以。为什么要用指针呢?因为有些题目需要修改结点的某些值,队列里压进去的只是原来的结点的副本,修改队列中的元素不改变原结点,这点需要注意,最好养成习惯用指针。
代码如下
#include <iostream>
#include <queue>
using namespace std;
const int Maxn=30+5;
struct node{
int data;
node* lchild;
node* rchild;
};
//输入
int n;
int inorder[Maxn],postorder[Maxn];
node* create(int inL,int inR,int poL,int poR){
//当inL==inR时是一个叶子结点还可以继续
if(inL>inR)
return NULL;
node* root=new node;
root->data=postorder[poR];
int k;
//找到中序遍历中的根节点,k保存中序遍历到根的下标
for(k=inL;k<=inR;k++){
if(inorder[k]==root->data)
break;
}
//左子树的节点数
int numLeft=k-inL;
root->lchild=create(inL,k-1,poL,poL+numLeft-1);
root->rchild=create(k+1,inR,poL+numLeft,poR-1);
return root;
}
int num=0;//已经输出的结点数,为了避免最后多一个空格
void BFS(node* root){
//注意元素类型是结点指针
queue<node*> q;
q.push(root);
while(!q.empty()){
node* now=q.front();
q.pop();
num++;
if(num<n)
printf("%d ",now->data);
else
printf("%d",now->data);
if(now->lchild!=NULL)
q.push(now->lchild);
if(now->rchild!=NULL)
q.push(now->rchild);
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&postorder[i]);
for(int i=0;i<n;i++)
scanf("%d",&inorder[i]);
node* root=create(0,n-1,0,n-1);
BFS(root);//层序遍历
return 0;
}