重建二叉树

题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8}和中序遍历列{4, 7, 2, 1, 5, 3, 8, 6},则重建出图 所示的二叉树并输出它的头结点。二叉树结点的定义如下:

Struct  BinaryTreeNode

{

     int                                        m_nValue;

    int  BinaryTreeNode*       m_pLeft;

   int   BinaryTreeNode*       m_pRight;

};


在前序遍历当中,第一个数总是树的根节点数值;在中序遍历当中,中间的数是树的根节点的数值,它左边的数是根节点左节点的数值,它右边的数是根节点右节点的数值。所以可以通过中序遍历来寻找根节点的数值。

由于在中序遍历序列中,有 3 个数字是左子树结点的值,因此左子树总共有 3 个左子结点。同样,在前序遍历的序列中,根结点后面的 3 个数字就是 3 个左子树结点的值,再后面的所有数字都是右子树结点的值。前序遍历和中序遍历两个序列中,分别找到了左右子树对应的子序列。



既然我们已经分别找到了左、右子树的前序遍历序列和中序遍历序列,我们可以用同样的方法分别去构建左右子树。也就是说,接下来的事情可以用递归的方法去完成。
在想清楚如何在前序遍历和中序遍历的序列中确定左、右子序列之后,我们可以写出如下的递归代码:

BinaryTreeNode* Construct(int* preorder,int* inorder,int length)
{
     //如果指针为空,就返回空指针
       if(preorder==NULL || inorder==NULLl || length<=0)
                        return NULL;
       return(ConstructCore(preorder,preorder+length-1),)
BinaryTreeNode* ConstructCore
(
       int* startPreorder,int* endPreorder,
       int*  startInorder,int*  endInorder
)
//前序遍历序列的第一个数字是根节点的值
int rootValue=startPreorder[0];
BinaryTreeNode* root=new  BinaryTreeNode();
root->m_nValue=rootValue;
root->m_pLeft=root->m_pRight=null;
//判断是否只有一个数
if(startPreorder==endPreorder)
  if(startInorder==endInorder && *startPreorder==*endPreorder)   
      return root;
else
throw std::exception("Invalid input.");

}

//在中序遍历中找到根节点的值
int * rootInorder=startInorder;
while(rootInorder<=endInorder && * rootInorder!= rootValue)
rootInorder++;
//没找到根节点
if(rootInorder==endInorder && * rootInorder!= rootValue)
throw std:exception("Invalid input");
int  leftLength=rootInorder-startInorder;//根节点的左子树的个数
int *leftPreorderEnd=startPreorder+leftLength;//在序列中根节点左边的一个数
if(leftLength>0)
{
    //构建左子树
root->m_pLeft=ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);
}
if(leftLength<endPreorder-startPreorder)
{
    //构建右子树
  root->m_pRight=ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值