#include"stdio.h"
#include"stdlib.h"
#define max 100
typedef struct node
{
char data;
struct node *rchild,*lchild;
} tree;
//创建两个字符串数组
void createArray(char q[],char w[])
{
gets(q);
gets(w);
}
//求字符串的长度
int Length(char q[])
{
int i=0;
while(*(q+i)!=0)
i++;
return i;
}
//按照先序输出二叉树
void show(tree *t)
{
if(t!=NULL)
{
show(t->lchild);
show(t->rchild);
printf("%c",t->data);
}
}
/*思路分析:
假设我们有这样的一个二叉树
1
2 3
4 5
那么这个二叉树的前序是这样的:12453
中序是这样的:42513
首先,其实大家都知道先找先序的第一个也就是1,然后再去中序中早这个节点
的位置(我习惯用下标表示),1 2453
425 1 3
也就是在前序中的1,通过seach函数,找到1所在的下标,也就是3,这样就通过中
序的序列来将这个二叉树的左右子树分开了,然后,我们不妨这样假设,就是将425这
个整体看做一个节点,与这并列的就是右节点3了,那么就是假设成这是最简单的一个
二叉树,只有根节点,和左右节点,这样的话,为根节点申请空间,然后又是为左节点
申请空间,这里我们重新思考,也就是对425这个整体右节点分析可以知道,425,又是
以2为根,45为左右节点,那么这样以来就出现了递归
可知道可以递归,然后把这个递归代码写出来,也需要好好想想,关键是控制,递归什么
时候停下来,这其实就是所有递归的最难的地方
分析见代码:*/
//最关键的一步,通过前序和中序创建二叉树
//pre1 是前序的最开始的点 pre2 是前序数组的结束下标点 in1,in2也一样,是中序的
void createTree(tree *&t,char q[],int pre1,int pre2,char w[],int in1,int in2)
{
t=(tree*)malloc(sizeof(tree));
t->data=q[pre1]; //因为前序的第一个节点一定是根节点
int i,k;
for(i=in1;i<=in2;i++)
{
if(q[pre1]==w[i])
{
k=i;break; //然后就是去中序中找下标
}
}
if(k==in1) //当找到的下标和in1相同,举个例子,就是1 2345和425 1 3那么第二次也就是以425来构建右子树
//就是前序245 中序425,这个时候又是2为根节点,左书只有4,那么给4创建完空间后,直接让4的左子树为空
t->lchild=NULL;
else
createTree(t->lchild,q,pre1+1,pre1+k-in1,w,in1,k-1); //控制每次分割出来的下标,例如,245,425,那么就是以这个为新的下标传进去递归
if(k==in2)
t->rchild=NULL;
else
createTree(t->rchild,q,pre1+k-in1+1,pre2,w,k+1,in2);
}
main()
{
tree *t;
char q[max],w[max];
int length;
createArray(q,w);
length=Length(q);
createTree(t,q,0,length-1,w,0,length-1);
show(t);
}
例如输入:12453
42513
输出:45231
#include"stdlib.h"
#define max 100
typedef struct node
{
char data;
struct node *rchild,*lchild;
} tree;
//创建两个字符串数组
void createArray(char q[],char w[])
{
gets(q);
gets(w);
}
//求字符串的长度
int Length(char q[])
{
int i=0;
while(*(q+i)!=0)
i++;
return i;
}
//按照先序输出二叉树
void show(tree *t)
{
if(t!=NULL)
{
show(t->lchild);
show(t->rchild);
printf("%c",t->data);
}
}
/*思路分析:
假设我们有这样的一个二叉树
1
2 3
4 5
那么这个二叉树的前序是这样的:12453
中序是这样的:42513
首先,其实大家都知道先找先序的第一个也就是1,然后再去中序中早这个节点
的位置(我习惯用下标表示),1 2453
425 1 3
也就是在前序中的1,通过seach函数,找到1所在的下标,也就是3,这样就通过中
序的序列来将这个二叉树的左右子树分开了,然后,我们不妨这样假设,就是将425这
个整体看做一个节点,与这并列的就是右节点3了,那么就是假设成这是最简单的一个
二叉树,只有根节点,和左右节点,这样的话,为根节点申请空间,然后又是为左节点
申请空间,这里我们重新思考,也就是对425这个整体右节点分析可以知道,425,又是
以2为根,45为左右节点,那么这样以来就出现了递归
可知道可以递归,然后把这个递归代码写出来,也需要好好想想,关键是控制,递归什么
时候停下来,这其实就是所有递归的最难的地方
分析见代码:*/
//最关键的一步,通过前序和中序创建二叉树
//pre1 是前序的最开始的点 pre2 是前序数组的结束下标点 in1,in2也一样,是中序的
void createTree(tree *&t,char q[],int pre1,int pre2,char w[],int in1,int in2)
{
t=(tree*)malloc(sizeof(tree));
t->data=q[pre1]; //因为前序的第一个节点一定是根节点
int i,k;
for(i=in1;i<=in2;i++)
{
if(q[pre1]==w[i])
{
k=i;break; //然后就是去中序中找下标
}
}
if(k==in1) //当找到的下标和in1相同,举个例子,就是1 2345和425 1 3那么第二次也就是以425来构建右子树
//就是前序245 中序425,这个时候又是2为根节点,左书只有4,那么给4创建完空间后,直接让4的左子树为空
t->lchild=NULL;
else
createTree(t->lchild,q,pre1+1,pre1+k-in1,w,in1,k-1); //控制每次分割出来的下标,例如,245,425,那么就是以这个为新的下标传进去递归
if(k==in2)
t->rchild=NULL;
else
createTree(t->rchild,q,pre1+k-in1+1,pre2,w,k+1,in2);
}
main()
{
tree *t;
char q[max],w[max];
int length;
createArray(q,w);
length=Length(q);
createTree(t,q,0,length-1,w,0,length-1);
show(t);
}
例如输入:12453
42513
输出:45231