首页 > 代码库 > 重建二叉树

重建二叉树

问题描述:

输入二叉树的前序遍历和后序遍历结果,请重建二叉树。假设输入的前序序列和后序序列都不含重复数字。

 

思路分析:

在二叉树的前序遍历中第一个数字总是树的根节点的值。但是在中序遍历中根节点的值位于序列中间,左子

树节点的值位于根节点值得左边,右子树节点的值位于根节点值的右边。因此我们需要扫描中序序列擦能找

到根节点的值。通过此方法可以分别找到了左右子树的前序序列和中序序列,然后可以用递归的方法实现。

 

参考代码:

//根据前序序列和中序序列重建二叉树
struct BinaryTreeNode
{
    int m_nValue;
    BinaryTreeNode *m_pLeft;
    BinaryTreeNode *m_pRight;
};

BinaryTreeNode* Construct(int *preorder,int *inorder,int length)
{
    if (preorder == NULL || inorder == NULL || length <= 0)
    {
        return NULL;
    }
    return ConstruceCore(preorder,preorder+length-1,inorder,inorder+length-1);
}

BinaryTreeNode* ConstruceCore(int *startPreorder,int *endPreorder,int *startInorder,int *endInorder)
{
    //前序遍历的第一个节点是根节点的值
    int rootValue = http://www.mamicode.com/startPreorder[0];
    BinaryTreeNode *pRoot = new BinaryTreeNode;
    pRoot->m_nValue = http://www.mamicode.com/rootValue;
    pRoot->m_pLeft = pRoot->m_pRight = NULL;

    if (startPreorder == endPreorder)
    {//只含一个元素的前序序列和中序序列。如果在这个这个序列中值相等则是子树的根节点,不等则说明序列有问题,作为递归的终止条件
        if ((startInorder == endInorder) && (*startInorder == *startPreorder))
        {
            return pRoot;
        }
        else
        {
            throw exception("Invalid input");
        }
    }

    //在中序遍历中寻找根节点的值
    int *rootInorder = startInorder;
    while((rootInorder <= endInorder) && (*rootInorder != rootValue))
    {
        rootInorder++;
    }

    if ((rootInorder == endInorder) && (*rootInorder != *endInorder))
    {
        throw exception("Invalid input");
    }

 

    //根据根节点在中序序列的位置确定中序序列中左右子树的起始位置。通过计算出的左右子树长度算出

    //左右子树在前序序列中的起始地址

    int leftLength = rootInorder - startInorder;
    int *leftPreorderEnd = startPreorder + leftLength;
    if (leftLength > 0)//左子树存在时递归创建左子树
    {
        pRoot->m_pLeft = ConstruceCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);
    }
    if (leftLength < endPreorder-startPreorder)//右子树存在时递归创建右子树。这个判断相当于间接判断了右子树是否存在
    {
        pRoot->m_pRight = ConstruceCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
    }
    return pRoot;
}

 

思考:

思想很简单,设置的变量比较多,容易混淆。特别要注意算序列起始地址。我在另一篇文章中给出了二叉树的递归遍历和

非递归遍历算法。

重建二叉树