重建二叉树

来源:互联网 发布:2012年cba总决赛数据 编辑:程序博客网 时间:2024/06/16 12:34

题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{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;elsethrow 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);}








0 0