• 重建二叉树


    • 题目描述:

    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}。二叉树结点的定义如下:

    struct BinaryTreeNode{
    	int m_nValue;
    	BinaryTreeNode* m_pLeft;
    	BinaryTreeNode* m_pRight;
    };
    
    • 分析:

       从此题开始,每个题在写代码之前都要按照之前的结题总结中的思路进行分析。首先是通过举例理解问题,体中也给出了一个例子,也就是根据二叉树的前序遍历和中序遍历来得到这个二叉树。接下来可以通过画图来实现这个重建二叉树的过程,从而发现其中的规律:根据二叉树的前序遍历可知,前序遍历中的每个结点都是一个子树的根结点;而在中序遍历序列中,根结点在序列的中间,左子树位于其左边,右子树位于其右边。最后试着能不能将复杂的问题分解成简单的问题。
       通过题目中所给的例子,前序遍历中第一个数字1就是根结点的值,根据中序遍历,找到根结点的值的位置。根据中序遍历的特点,在根结点值1前边的3个数字都是左子树结点的值,位于1后边的数字都是右子树结点的值。那么,在前序遍历中,根结点1后边的3个数字就是左子树结点的值,再后边的所有数字都是右子树结点的值。这样,我们就在前序遍历和中序遍历两个序列中,分别找到了左子树、右子树对应的前序遍历的子序列和中序遍历的子序列。接下来,就可以用递归的方法来分别构建左子树和右子树了,过程如下图。

       

      enter description here

       

       

       

      enter description here

       

       

      简单总结:从前序中确定根节点,然后在中序中找到根,从而将中序序列分为左右子树的中序遍历序列;再根据左右子树节点的个数,在前序遍历中将前序序列分为左右子树的前序遍历序列,接下来就是递归过程。
      接下来还有一点要考虑的就是鲁棒性了,通过列举各种可能的测试用例来考虑。比如几种特殊的情况是否会导致程序崩溃?1、输入序列的指针为空或长度length为0;2、输入的序列不匹配;3、以及用各种不同形状的二叉树检验程序正确性(完全二叉树、普通二叉树、所有结点只有左(右)孩子的树)
      代码如下:

      BinaryTreeNode* ConstructBinaryTree(int* preorder, int* inorder, int length)
        {
        	// 输入空指针或长度小于等于0时返回NULL
        	if (preorder == NULL || inorder == NULL || length <= 0)
        		return NULL;
        
        	// 创建根结点,前序序列中的第一个值为根结点的值
        	BinaryTreeNode* root = new BinaryTreeNode();
        	root->m_nValue = preorder[0];
        	root->m_pLeft = NULL;
        	root->m_pRight = NULL;
        
        	// 只有一个结点的情况
        	if (length == 1 && *preorder == *inorder)
        		return root;
        	else if (length == 1 && *preorder != *inorder)
        		throw exception("Invalid input");
        
        	// 在中序序列中找到根结点的位置
        	int* rootinorder = inorder;
        	int inorderlength = 0;
        	while (*rootinorder != root->m_nValue && inorderlength < length)
        	{
        		++rootinorder;
        		++inorderlength;
        	}
        	if (inorderlength == length && *rootinorder != root->m_nValue)
        		throw exception("Invalid input");
        
        	int leftlength = rootinorder - inorder;
        	int rightlength = length - leftlength - 1;
        	if (leftlength > 0)
        	{ //构建左子树
        		root->m_pLeft = ConstructBinaryTree(preorder+1,inorder,leftlength);
        	}
        	if (rightlength > 0)
        	{ //构建右子树
        		root->m_pRight = ConstructBinaryTree(preorder+leftlength+1,rootinorder+1,rightlength);
        	}
        	return root;
        }
      
  • 相关阅读:
    调查问卷
    SQL 基础学习(1):下载DB Browser for SQLite. 下载graphviz(为了使用Rails ERD的前提)出现❌,已debug.
    路由完整实例代码
    如何自定义JSTL标签与SpringMVC 标签的属性中套JSTL标签报错的解决方法
    CSS样式表、JS脚本加载顺序与SpringMVC在URL路径中传参数与SpringMVC 拦截器
    SpringMVC的解释与搭建Maven私有代理服务器
    单调队列 bzoj3126 [Usaco2013 Open]Photo
    二分图 crf的军训
    单调队列 JC loves Mkk
    测试开发CICD——Git——window上安装git——配置基本信息
  • 原文地址:https://www.cnblogs.com/Bill-LHR/p/6769389.html
Copyright © 2020-2023  润新知