zoukankan      html  css  js  c++  java
  • 重建二叉树

    问题描述:

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

    思路分析:

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

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

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

    参考代码:

    //根据前序序列和中序序列重建二叉树
    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 = startPreorder[0];
        BinaryTreeNode *pRoot = new BinaryTreeNode;
        pRoot->m_nValue = 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;
    }

    思考:

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

    非递归遍历算法。

    生命在于折腾,生活就是如此的丰富多彩
  • 相关阅读:
    日历生成器 v1.0 PHP
    原理
    Math.Round默认采用的不是四舍五入法, 而是四舍六入的银行家算法, 如何找回四舍五入法?
    .Net Attribute特性
    转: 如何删除windows service (How to delete a windows service)
    PowerShell入门
    Session, Cookie, Web.config中的cookieless总结
    Assembly.CreateInstance()与Activator.CreateInstance()方法 (转)
    Telnet与远程桌面
    Setting Meta Tags
  • 原文地址:https://www.cnblogs.com/Mr-Zhong/p/4120346.html
Copyright © 2011-2022 走看看