• 重建二叉树


    问题描述:

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

    思路分析:

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

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

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

    参考代码:

    //根据前序序列和中序序列重建二叉树
    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;
    }

    思考:

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

    非递归遍历算法。

    生命在于折腾,生活就是如此的丰富多彩
  • 相关阅读:
    c++ 指定目录下的文件遍历
    c++ 实现键盘钩子
    c++ 用模板类实现顺序储存的线性表
    c++ 递归算法实现排列组合
    matlab 基础知识
    QT 给工程添加图片
    QT5.9 QString和字符串转换的乱码问题
    【内核】——进程3,内核同步
    Java多线程——Thread的native底层实现
    【内核】——文件和文件系统的内部结构4 系统调用的实现
  • 原文地址:https://www.cnblogs.com/Mr-Zhong/p/4120346.html
Copyright © 2020-2023  润新知