【解题】重建二叉树(C++实现)

题目描述:输入二叉树的前序遍历和中序遍历结果 ,请重建出该二叉树,返回其头节点并给出后序遍历序列。假设输入的遍历序列不包含重复数字。

题目分析:
      根据前序遍历和中序遍历的特征,我们知道在前序遍历序列中,第一个数字总是树的根节点;而在中序遍历中根节点的值在序列中间,左子树的节点值一定位于根节点左边,右子树的节点值一定位于根节点右边。这样我们结合前序遍历和中序遍历序列,就可以确定出树的根节点及其左右子树节点,对于左右子树,递归地采用这种方法即可。

      拿一个实例来说明上述算法描述:假设输入前序遍历序列{1,2,4,7,3,5,6,8}及中序遍历序列{4,7,2,1,5,3,8,6}。我们根据前序遍历序列知道:1是树的根节点,再结合中序遍历序列,知道{4,7,2}为根节点1的左子树,{5,3,8,6}为根节点1的右子树。对于两棵左右子树,重复上述算法即可重建整棵二叉树。

      我们重用前面的二叉树链表实现代码给出重构二叉树的实现:

Node* BinaryTree::Reconstruct(int *preorder, int *inorder, int length)
{
    if (preorder == NULL || inorder == NULL || length <= 0)
        return NULL;
    return ReconstructCore(preorder, preorder + length - 1, inorder, inorder + length - 1);
}
Node* BinaryTree::ReconstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder)
{
    //前序遍历第一个数字是根节点
    int rootValue = startPreorder[0];
    Node* root = new Node();
    root->data = rootValue;
    if (startPreorder == endPreorder)
    {
        if (startInorder == endInorder&&*startPreorder == *startInorder)
            return root;
        else
            throw exception("Invalid input!");
    }

    //中序遍历中找到根节点
    int *rootInorder = startInorder;
    while (rootInorder <= endInorder&&*rootInorder != rootValue)
        ++rootInorder;

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

    //重建左右子树
    int leftLength = rootInorder - startInorder;
    int *leftPreorderEnd = startPreorder + leftLength;
    if (leftLength > 0)   //左子树不为空
    {
        root->p_lChild = ReconstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1);
        root->p_lChild->p_Parent = root;
    }
    if (leftLength < endPreorder - startPreorder)  //重建右子树
    {
        root->p_rChild = ReconstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder);
        root->p_rChild->p_Parent = root;
    }

    return root;
}

几点说明:

  • 上述代码中包含了大量的指针加减运算,读者应注意理解,实际上是运算结果指针的移动
  • 重建二叉树的过程中并没有指定索引,建议重构完成之后再指定索引值。
  • 后序遍历可以重用前面已经实现的代码
  • 同样地,当给出后序遍历和中序遍历序列后,也可以用类似的方法重构出二叉树。但是给出前序遍历和后序遍历则不能完成重构(有兴趣的读者可以想想为什么)。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值