题目:
输入某二叉树的前序遍历和中序遍历,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含有重复的数字。
例如,前序遍历序列:{1,2,4,7,3,5,6,8},中序遍历序列:{4,7,2,1,5,3,8,6}
则重建出的二叉树如下所示,并输出它的头结点1。
基本思想:
前序遍历:
前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。
中序遍历:
中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。
1、先序遍历序列的第一个元素必定是根节点,可以由此获取二叉树的根节点。
2、根据根节点,在中序遍历序列中查找该节点,由中序遍历的性质可知,中序遍历中该根节点左边的序列必定在根节点的左子树中,而根节点右边的序列必定在右子树中。由此可以知道先序遍历中左子树以及右子树的起止位置。
3、分别对左子树和右子树重复上述的过程,直至所有的子树的起止位置相等时,说明已经到达叶子节点,遍历完毕。
#include <iostream>
#include <deque>
using namespace std;
//二叉树结点定义
typedef struct BiTreeNode{
int data;
//左右孩子指针
struct BiTreeNode *lchild;
struct BiTreeNode *rchild;
}BiTreeNode,*BiTree;
//访问函数
void Visit(BiTree T)
{
if(T->data != -1)
cout<<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);
}
}
BiTree constructor(int * startP,int * endP,int * startI,int * endI)
{
//前序遍历序列的第一个数字是根节点的值
int rootValue=startP[0];
BiTree root;
root = (BiTree)malloc(sizeof(BiTreeNode));
root->data=rootValue;
root->lchild=root->rchild=NULL;
if(startP==endP)
{
if(startI==endI && *startP==*startI)
return root;
else
return NULL;
}
//在中序遍历中找到根节点的值
int * rootI=startI;
while(rootI<=endI && *rootI!=rootValue)
++rootI;
if(rootI==endI && *rootI!=rootValue)
return NULL;
int leftlen=rootI-startI;
int *leftPE=startP+leftlen;
if(leftlen>0)
{
//构建左子树
root->lchild=constructor(startP+1,leftPE,startI,rootI-1);
}
if(leftlen<endP-startP)
{
//构建右子树
root->rchild=constructor(leftPE+1,endP,rootI+1,endI);
}
return root;
}
BiTree foo(int * pre,int * ino,int len)
{
if(pre==NULL || ino==NULL ||len<=0)
return NULL;
return constructor(pre,pre+len-1,ino,ino+len-1);
}
void main()
{
int pre[]={1,2,4,7,3,5,6,8};
int ino[]={4,7,2,1,5,3,8,6};
int len=sizeof(pre)/sizeof(pre[0]);
BiTree T = foo(pre,ino,len);
cout<<"二叉树根节点:";
cout<<T->data<<endl;
cout<<"先序遍历:";
PreOrder(T);
cout<<endl;
cout<<"中序遍历:";
InOrder(T);
cout<<endl;
cout<<"后序遍历:";
PostOrder(T);
cout<<endl;
}