一、已知二叉树的先序序列和中序序列重建二叉树
- 示意图:
- 根据示意图可以得到如下代码:
node* create(int preL,int preR,int inL,int inR){
if(preL > preR){
return NULL;//先序序列的长度小于等于0时,直接返回
}
node* root = new node; //新建一个结点,用来存放当前二叉树的根节点
root->data = preArr[preL]; //新结点的数据域为根结点的值
int k;
for(k = inL;k <= inR;k++){
if(preArr[preL] == inArr[k]){ //在中序序列中找到inArr[k] == preArr[preL]的结点
break;
}
}
int numLeft = k - inL; //左子树的结点个数
//左子树的先序区间为[preL+1,preL+numLeft],中序区间为[inL,k-1]
//返回左子树的根结点地址,赋值给root的左指针
root->lchild = create(preL+1,preL+numLeft,inL,k-1);
//右子树的先序区间为[preL+numLeft+1,preR],中序区间为[k+1,inR]
//返回右子树的根结点地址,赋值给root的右指针
root->rchild = create(preL+numLeft+1,preR,k+1,inR);
return root; //返回根结点的地址
}
二、已知二叉树的后序序列和中序序列重建二叉树
思想同上,只不过在后序序列中最后一个结点才是二叉树的根结点
示例代码:
node* create(int postL,int postR,int inL,int inR){
if(postL > postR){
return NULL;
}
node* root = new node;
root->data = postArr[postR];
int k;
for(k = inL;k <= inR;k++){
if(inArr[k] == postArr[postR]) break;
}
int numLeft = k - inL;
root->lchild = create(postL,postL+numLeft-1,inL,k-1);
root->rchild = create(postL+numLeft,postR-1,k+1,inR);
return root;
}
三、总结
要构建一个二叉树必须给出中序序列,中序序列可以与先序序列、后序序列、层次序列中任意一个来构建唯一的二叉树;但后三者两两搭配或是三个一起都无法构建唯一的二叉树。原因是先序、后序、层序均是提供根结点,作用是相同的都必须由中序序列来区分出左右子树。
通过先序序列和中序序列构建二叉树的整个程序示例代码:
#include <iostream>
using namespace std;
const int maxn = 1000 + 5;
int preArr[maxn] = {1,2,4,5,3,6}; //先序序列
int inArr[maxn] = {4,2,5,1,6,3}; //中序序列
typedef struct node{
int data;
node* lchild;
node* rchild;
};
node* create(int preL,int preR,int inL,int inR){
if(preL > preR){
return NULL;//先序序列的长度小于等于0时,直接返回
}
node* root = new node; //新建一个结点,用来存放当前二叉树的根节点
root->data = preArr[preL]; //新结点的数据域为根结点的值
int k;
for(k = inL;k <= inR;k++){
if(preArr[preL] == inArr[k]){ //在中序序列中找到inArr[k] == preArr[preL]的结点
break;
}
}
int numLeft = k - inL; //左子树的结点个数
//左子树的先序区间为[preL+1,preL+numLeft],中序区间为[inL,k-1]
//返回左子树的根结点地址,赋值给root的左指针
root->lchild = create(preL+1,preL+numLeft,inL,k-1);
//右子树的先序区间为[preL+numLeft+1,preR],中序区间为[k+1,inR]
//返回右子树的根结点地址,赋值给root的右指针
root->rchild = create(preL+numLeft+1,preR,k+1,inR);
return root; //返回根结点的地址
}
void postOrder(node* root){ //后序遍历
if(root){
postOrder(root->lchild);
postOrder(root->rchild);
cout<<root->data<<" ";
}
}
int main(void){
node* root = create(0,5,0,5);
cout<<"后序序列为:";
postOrder(root); //输出后序序列,观察二叉树构建是否正确
cout<<endl;
return 0;
}
画出此时的二叉树:
后序序列:4 5 2 6 3 1
程序结果:
PAT上有一道类似的题:
PAT1020