重建二叉树

何海涛老师的《剑指offer》中的面试题6,觉着有难度,记录在此。

题目要求根据给出的前序遍历{1,2,4,7,3,5,6,8},中序遍历{4,7,2,1,5,3,8,6}重建它的二叉树,并且输出头指针。

首先必须知道前序遍历中序遍历的概念。在二叉树遍历中第一个总是根结点,但在中序遍历中根结点在中间。上述给的1就是根结点,中序遍历中1左边的就是左边结点,而右边的就是右边结点。这样接着在分出来的左边结点和右边结点中分别递归的方法完成。

递归的难点在于确定结束的条件,自己果然是经常写低级代码写习惯了,尝试多次未果,参考了何老师的代码:

1.首先取先序遍历的头结点生成一个二叉树结点。

2.利用该头节点将先序遍历,中序遍历中的左右结点序列分开得到left_preorder,right_preorder,left_inorder,right_inorder。

3.利用左中序序列的长度判断对应递归调用。

4.递归的结束条件是:中序遍历的首尾指针相同,且先序遍历序列首值与中序首值相同。

自己实现的代码如下:

BinaryTree* ConstructCore(int *start_preorder, int *end_preorder, int *start_inorder, int *end_inorder)
{
    int root = start_preorder[0];
    BinaryTree *pNode = new BinaryTree(root);

    if(start_preorder == end_preorder)
    {
        if(*start_preorder == *start_inorder && start_inorder == end_inorder)
            return pNode;
        else
        {
            throw std::exception("invalid input");
        }
    }

    int *pMove = start_inorder;
    int left_elem_count = 0;

    while ( pMove != end_inorder && *pMove != root)
    {
        ++left_elem_count;
        ++pMove;
    }

    if(left_elem_count > 0)
    {
        
        pNode ->pLef = ConstructCore(start_preorder+1, start_preorder+left_elem_count, start_inorder, start_inorder+left_elem_count-1);

    }
    if(left_elem_count < end_preorder - start_preorder)
    {
        pNode ->pRig = ConstructCore(start_preorder+left_elem_count+1, end_preorder, start_inorder+left_elem_count+1, end_inorder);
    }

    return pNode;
}

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

}
View Code


 

原文地址:https://www.cnblogs.com/bestwangjie/p/5515587.html