• 重建二叉树


    关于二叉树的重建,我总结如下,并以图文的形式展示:

    一颗二叉树,已知先序遍历和中序遍历,要求还原出二叉树,问题不难,关键是细节:

    思想:

    1、先序遍历序列的第一个元素一定定是根节点,可以由此获取二叉树的根节点。

    2、在中序遍历序列中查找到根节点,由中序遍历的性质可知,中序遍历中该根节点左边的序列一定在根节点的左子树中,而根节点右边的序列一定在右子树中。由此可以知道先序遍历中左子树以及右子树的起止位置。

    3、分别对左子树和右子树重复上述的过程,直至所有的子树的起止位置相等时,说明已经到达叶子节点。

    以上过程,递归就显得很重要:

    先上一张图:


    假设这是需要我们重新构建的二叉树。

    此二叉树的前序遍历为:1,2,4,7,3,5,6,8

                       中序遍历为:4,7,2,1,5,3,8,6

    再看:


    同样的方法在子树中递归重建子树,以下是代码:

    //声明重构
    BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder);
    
    //重构
    BinaryTreeNode* 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);
    }
    
    BinaryTreeNode* ConstructCore
    (
        int* startPreorder, int* endPreorder, 
        int* startInorder, int* endInorder
    )
    {
        //前序遍历序列的第一个数字是根结点的值
        int rootValue = startPreorder[0];
    
    	//重构第一个根节点
        BinaryTreeNode* root = new BinaryTreeNode();
        root->m_nValue = rootValue;
        root->m_pLeft = root->m_pRight = NULL;
    
    	//前序的头和尾相等的时候
        if(startPreorder == endPreorder)
        {
    		//并且中序头和尾也相等,前序头和中序头相等,只说明只有一个节点
    		if (startInorder == endInorder && *startPreorder == *startInorder)
    		{
                return root;
    		}
        }
    
        // 在中序遍历中找到根结点的值
        int* rootInorder = startInorder;
    	while (rootInorder <= endInorder && *rootInorder != rootValue)
    	{
            ++ rootInorder;
    	}
    
    	if (rootInorder == endInorder && *rootInorder != rootValue)
    	{
    		cout << "非法序列" << endl;
    		return;
    	}
    
    	//while循环结束,跳过,意思是找到了根节点
    	//求出左子树的长度leftLength
        int leftLength = rootInorder - startInorder;  //虽然是指针相减,但指针内部也是整数
        int* leftPreorderEnd = startPreorder + leftLength; //找到前序遍历左子树最后一个节点
        if(leftLength > 0)
        {
            // 构建左子树
    		//startPreorder + 1 原来前序的头往前走一个
            root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, 
                startInorder, rootInorder - 1);
        }
    
        if(leftLength < endPreorder - startPreorder)
        {
            // 构建右子树
            root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder,
                rootInorder + 1, endInorder);
        }
        return root;
    }
    赐教!




  • 相关阅读:
    Win7 安装 IIS 7.5 及部署 .NET 程序到 IIS 的内容杂记
    乐嘉,你快回来
    AMD将要嫁他人?
    高精度运算(运算符重载)
    魔数卡牌
    C语言"#","#@"和"##"在宏定义中的使用技巧
    CentOS7下安装FTP服务
    Linux下FTP的安装和登陆
    怎么让FOXMAIL关了以后在右下角自动收取邮件
    在CentOS7上安装ftp服务器用于保存服务端上传的图片。
  • 原文地址:https://www.cnblogs.com/melons/p/5791854.html
Copyright © 2020-2023  润新知