输入某二叉树的前序遍历和中序遍历,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含有重复的数字。
例如,前序遍历序列:{1,2,3,7,3,5,6,8},中序遍历序列:{4,7,2,1,5,3,8,6}
根据先序遍历和中序遍历还原二叉树的主要思想:
1、先序遍历序列的第一个元素必定是根节点,可以由此获取二叉树的根节点。
2、根据根节点,在中序遍历序列中查找该节点,由中序遍历的性质可知,中序遍历中该根节点左边的序列必定在根节点的左子树中,而根节点右边的序列必定在右子树中。由此可以知道先序遍历中左子树以及右子树的起止位置。
3、分别对左子树和右子树重复上述的过程,直至所有的子树的起止位置相等时,说明已经到达叶子节点,遍历完毕。
#include<iostream.h>
#include<malloc.h>
struct treenode
{
int date;
treenode *leftch;
treenode *rightch;
};
bool tree=true;
treenode *constructcore(int preorder[],int prestart,int preend,int inorder[],int instart,int inend)
{
int rootnum=preorder[prestart];
treenode *root=(treenode *)malloc(sizeof(treenode));
root->date=rootnum;
root->leftch=NULL;
root->rightch=NULL;
if(preend==prestart)
{
if(instart==inend&&preorder[prestart]==inorder[instart])
return root;
else
{
tree=false;
return NULL;
}
}
int rootinorderindex=-1;
for(int i=instart;i<=inend;i++)
if(inorder[i]==rootnum)
rootinorderindex=i;
if(rootinorderindex==-1)
{
tree=false;
return NULL;
}
if(rootinorderindex-instart>0) //左子树不为空
root->leftch=constructcore(preorder,prestart+1,prestart+rootinorderindex-instart,inorder,instart,rootinorderindex-1);
if(inend-rootinorderindex>0) //右子树不为空
root->rightch=constructcore(preorder,prestart+rootinorderindex-instart+1,preend,inorder,rootinorderindex+1,inend);
return root;
}
treenode *construct(int preorder[],int inorder[],int length)
{
if(preorder==NULL||inorder==NULL||length<1)
return NULL;
return constructcore(preorder,0,length-1,inorder,0,length-1);
}
void preordertree(treenode *root)
{
if(root==NULL)
return;
cout<<root->date<<" ";
preordertree(root->leftch);
preordertree(root->rightch);
}
void inordertree(treenode *root)
{
if(root==NULL)
return;
inordertree(root->leftch);
cout<<root->date<<" ";
inordertree(root->rightch);
}
void main()
{
int preorder[]={1,2,4,7,3,5,6,8},inorder[]={4,7,2,1,5,3,8,6};
treenode *root=NULL;
root=construct(preorder,inorder,sizeof(preorder)/sizeof(int));
if(tree)
{
preordertree(root);
cout<<endl;
inordertree(root);
cout<<endl;
}
}