题目:输入二叉树的前序和中序遍历结果,请重建出二叉树。假如输入的前序遍历和中序遍历结果中不含重复数字(关键,如果重复了,该程序就不适用用了)。如输入的前序遍历是{1,2,4,7,3,5,6,8,}和中序遍历{4,7,2,1,5,3,8,6},请重建出它的二叉树。
二叉树的结构
分析图
如图中所示,
1:前序遍历第1个结点是根结点,对应了中序遍历的root的位置,就可以根据中序遍历序列得出1前面是该二叉树的左子树,后面是该二叉树的右子树。
2:根据前序遍历根节点得出下一个节点是左子树的根节点。
3:根据中序遍历得出根节点1的位置,然后和前序遍历的root结点位置相加再加1,就得到了右子树的根节点是3
4:依次类推,利用递归直到查完整个序列。
代码:
/*************************************************************************
> File Name: 06.c
> Author: ma6174
> Mail: ma6174@163.com
> Created Time: Mon 03 Mar 2014 08:01:53 PM PST
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct BTree /*ding yi er cha shu*/
{
int data;
struct BTree *left;
struct BTree *right;
}btree,*BTREE;
BTREE ConstructCode(int *ptree_start,int *ptree_end,int *itree_start,int *itree_end);/*主递归函数*/
BTREE Construct(int *ptree,int *itree,int length); /*调用递归函数重建二叉树,返回根节点位置*/
void P_BTree(BTREE btree); /*先序遍历二叉树函数*/
void I_BTree(BTREE btree); /*中序遍历二叉树函数*/
void A_BTree(BTREE btree); /*后序遍历二叉树函数*/
void P_BTree(BTREE btree) /*先序遍历二叉树函数*/
{
if(btree==NULL)
return;
printf("%d ",btree->data);
if(btree->left!=NULL)
{
P_BTree(btree->left);
}
if(btree->right!=NULL)
{
P_BTree(btree->right);
}
}
void I_BTree(BTREE btree) /*中序遍历二叉树函数*/
{
if(btree==NULL)
return;
if(btree->left!=NULL)
{
I_BTree(btree->left);
}
printf("%d ",btree->data);
if(btree->right!=NULL)
{
I_BTree(btree->right);
}
}
void A_BTree(BTREE btree) /*后序遍历二叉树函数*/
{
if(btree==NULL)
return;
if(btree->left!=NULL)
{
A_BTree(btree->left);
}
if(btree->right!=NULL)
{
A_BTree(btree->right);
}
printf("%d ",btree->data);
free(btree); /*利用后续遍历释放申请的空间*/
}
BTREE Construct(int *ptree,int *itree,int length)
{
if(ptree==NULL || itree==NULL || length<=0)
return NULL;
return ConstructCode(ptree,ptree+length-1,itree,itree+length-1);
}
/****************************************************************
*args:
* ptree_start:先序遍历开始位置指针
* ptree_end:先序遍历结束位置指针
* itree_start:中序遍历开始位置指针
* itree_end:中序遍历结束位置指针
****************************************************************/
BTREE ConstructCode(int *ptree_start,int *ptree_end,int *itree_start,int *itree_end)
{
BTREE root_node;
root_node=(BTREE)malloc(sizeof(btree));
root_node->data=ptree_start[0]; /*根节点*/
root_node->left=NULL;
root_node->right=NULL;
if(ptree_start==ptree_end) /*该节点是子树最后一个节点*/
{
if(itree_start==itree_end && *ptree_start==*ptree_end)
{
return root_node;
}else
{
printf("ConstructCode is error!\n");
exit(1);
}
}
int *tmp_itree=itree_start;
int left_length=0;
while((*itree_start!=root_node->data) && (itree_start<itree_end))/*在中序遍历中寻找跟节点的指针*/
{
itree_start++;
}
left_length=itree_start-tmp_itree; /*根节点在中序遍历中的位置,用于求在先序遍历中右子树的开始位置*/
if(left_length>0) /*左子树递归*/
{
root_node->left=ConstructCode(ptree_start+1,ptree_start+left_length,tmp_itree,itree_start-1);
}
if(left_length<(ptree_end-ptree_start)) /*右子树递归,pend-pstart>left_length说明遍历序列比左子树长,右子树有节点*/
{
root_node->right=ConstructCode(ptree_start+left_length+1,ptree_end,itree_start+1,itree_end);
}
return root_node;
}
int main()
{
int ptree[8]={1,2,4,7,3,5,6,8};
int itree[8]={4,7,2,1,5,3,8,6};
int *p; /*测试为空的情况*/
int *i;
BTREE root;
root=Construct(ptree,itree,8);
if(root==NULL)
{
printf("the tree is NULL\n");
return 1;
}
printf("先序:");
P_BTree(root);
printf("\n");
printf("中序:");
I_BTree(root);
printf("\n");
printf("后序:");
A_BTree(root);
printf("\n");
return 0;
}