下面三种序列可以唯一的构造唯一的一棵二叉树:
前序序列和中序序列构造二叉树
后序序列和中序序列构造二叉树
层次遍历序列和中序遍历序列构造二叉树
#include
#include
#include
#include
#define MaxSize 10
typedef struct BTNode{
char data;
struct BTNode *lchild,*rchild;
}BTNode,*BiTree;
//根据前序序列,中序序列建造一棵二叉树
//参数含义:pre[]前序序列 in[]中序序列
// L1 R1用于指定pre[]的搜索区域
// L2 R2用于指定in[]的搜索区域
BiTree createBiTree(char pre[],char in[],int L1,int R1,int L2,int R2){
if(L1>R1){
return NULL;//递归出口
}
BTNode *s =(BTNode*)malloc(sizeof(BTNode));
s->lchild =NULL;
s->rchild =NULL;
s->data=pre[L1];
int i;
//根据中序序列的特性,元素左边的元素属于该节点的左孩子序列,右边则是右孩子序列
for(i=L2;i<=R2;i++){
if(pre[L1]==in[i]) break;//在中序序列找到该元素
}
s->lchild=createBiTree(pre,in,L1+1,L1+i-L2,L2,i-1);//递归
s->rchild=createBiTree(pre,in,L1+i-L2+1,R1,i+1,R2);
return s;
}
//根据后序中序建立二叉树
BiTree createBiTree2(char post[],char in[],int L1,int R1,int L2,int R2){
if(L1>R1){
return NULL;//递归出口
}
BTNode *s =(BTNode*)malloc(sizeof(BTNode));
s->lchild =NULL;
s->rchild =NULL;
s->data=post[R1];//后序序列最后一个节点为根节点
int i;
//根据中序序列的特性,元素左边的元素属于该节点的左孩子序列,右边则是右孩子序列
for(i=L2;i<=R2;i++){
if(post[R1]==in[i]) break;//在中序序列找到该元素
}
//递归 面试官:为什么要减去L2? 答:递归传下去的是整个数组,需要根据参数找到递归出口,-L2是缩小查找范围
s->lchild=createBiTree2(post,in,L1,L1+i-L2-1,L2,i-1);
s->rchild=createBiTree2(post,in,L1+i-L2,R1-1,i+1,R2);
return s;
}
//该函数用于在中序序列中找到key,返回其位置
//参数含义:in[]:中序序列 key:所要查找元素 L,R:查找范围
int serach(char in[],char key,int L,int R){
for(int i=L;i<=R;i++){
if(in[i]==key) return i;
}
return -1;
}
//因为在中序序列元素的左面的元素在层次遍历序列中并不连续,所以需要用子序列函数将并不连续的序列连续起来
//为什么要连续起来?因为需要连续起来才能和中序序列构造出二叉树
//思路:在中序序列里查找到一个范围,从这个范围里遍历元素,在层次遍历序列里找该元素
//参数含义:sublevel[]:存放子序列数组 level[]:层次遍历序列 in[]:中序序列 n:level层次序列长度 L,R:查找范围
void getSubLevel(char sublevel[],char level[],char in[],int n,int L,int R){
int k=0;
for(int i=0;iR) return NULL;
BTNode *s =(BTNode*)malloc(sizeof(BTNode));
s->lchild =NULL;
s->rchild =NULL;
s->data=level[0];
int i=serach(in,level[0],L,R);
//找到i便可以确定左右子树答大小
int LN=i-L; char LLevel[LN];
int RN=R-i; char RLevel[RN];
getSubLevel(LLevel,level,in,n,L,i-1);//得到子序列
getSubLevel(RLevel,level,in,n,i+1,R);
s->lchild=createBiTree3(LLevel,in,LN,L,i-1);//用子序列递归
s->rchild=createBiTree3(RLevel,in,RN,i+1,R);
return s;
}
void visit(BiTree T) {
printf("%c ",T->data);
}
//前序遍历
void PreOrder(BiTree T){
if(T!=NULL){
visit(T);//根
PreOrder(T->lchild);//左
PreOrder(T->rchild);//右
}
}
//中序遍历
void InOrder(BiTree T){
if(T!=NULL){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
//后序遍历
void PostOrder(BiTree T){
if(T!=NULL){
PostOrder(T->lchild);
PostOrder(T->rchild);
visit(T);
}
}
//层次遍历
void level(BiTree T){
if(T!=NULL){
int front=0;
int rear=0;
BiTree queue[MaxSize];
BiTree p;
p=T;
rear=(rear+1)%MaxSize;
queue[rear]=p;
while(rear!=front){
front=(front+1)%MaxSize;
p=queue[front];
visit(p);
if(p->lchild!=NULL){
rear=(rear+1)%MaxSize;
queue[rear]=p->lchild;
}
if(p->rchild!=NULL){
rear=(rear+1)%MaxSize;
queue[rear]=p->rchild;
}
}
}
}
int main(){
char c[]="ABDECFGH";//前序序列
char d[]="DBEACGFH";//中序序列
char p[]="DEBGHFCA";//后序序列
char l[]="ABCDEFGH";//层次遍历序列
BTNode *r=createBiTree(c,d,0,7,0,7);
BTNode *r2=createBiTree2(p,d,0,7,0,7);
BTNode *r3=createBiTree3(l,d,8,0,7);
printf("前序序列为:");
PreOrder(r);
printf("\n");
printf("后序序列为:");
PostOrder(r2);
printf("\n");
printf("中序序列为:");
InOrder(r3);
printf("\n");
printf("层次遍历为:");
level(r3);
printf("\n");
}
代码运行截图: