草庐IT

树的前序遍历与中序遍历构造二叉树和树的中序遍历与后序遍历构造二叉树

允歆辰丶 2023-06-11 原文

目录

一.树的前序遍历与中序遍历构造二叉树

1.题目描述

2.问题分析

3.代码实现

二.树的中序遍历与后序遍历构造二叉树

1.题目描述

2.问题分析

3.代码实现

三.问题思考


一.树的前序遍历与中序遍历构造二叉树

1.题目描述

给定两个整数数组 preorderinorder ,其中 preorder 是二叉树的先序遍历inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

力扣:力扣

2.问题分析

我们根据 preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]来分析如何手动构建一颗二叉树

① 首先根据前序遍历的特点,通过preorder我们可知3为根结点,再根据中序遍历的特点,通过inorder 我们可知3为根结点的左子树有{9},右子树有{15,20,7}这些元素

② 因为已经划分了左右子树,再看preorder,此时9为结点3左子树的根结点,20为结点3右子树的根结点,再看inorder ,此时左子树已经完成,结点20的左子树有{15},右子树有{7};

③ 因为已经划分了左右子树,再看preorder,此时15为结点20左子树的根结点,20为结点3右子树的根结点,,此时preorder数组已经遍历完毕,整棵树也已经构建完毕了

手动已经实现了二叉树的构建,其实关键一共就两步,第一步是在前序遍历列表寻找根结点(也就是子树的第一个元素),第二步是在中序遍历寻找根结点的位置,根结点左边为左子树的结点范围,右边为右子树的结点范围.

接下来我们看代码实现(看代码实现的代码),代码递归实现和我们手动实现的顺序不一样,我们是同时寻找左右子树,递归是先构建根结点,然后构建左子树,最后构建右子树,直到全部遍历完成.(按照前序遍历(根左右)的方式)

大致的顺序如下:没有一步步递归,只画出了关键的步骤

 

其实不加    if(index==preorder.length)return null; 判断也没有错,只不过加上更加直观

3.代码实现

    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();

    public TreeNode buildTree(int[] preorder, int[] inorder) {
          for (int i = 0; i < inorder.length; ++i) {
            map.put(inorder[i], i);
        }
       return buildTreeHelper(preorder,inorder,0,inorder.length-1);

    }
    int index=0;
    public TreeNode buildTreeHelper(int[] preorder, int[] inorder,int left,int right){
        if(index==preorder.length){
            return null;
        }
        if(left>right){
            return null;
        }
        //1.前序数组的第一个为根结点
        int val=preorder[index++];
        TreeNode root=new TreeNode(val);
        //2.寻找中序遍历的左右子树的范围
        int mid=map.get(val);
        root.left=buildTreeHelper(preorder,inorder,left,mid-1);
        root.right=buildTreeHelper(preorder,inorder,mid+1,right);
        return root;

    }

二.树的中序遍历与后序遍历构造二叉树

1.题目描述

给定两个整数数组 inorderpostorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

力扣:力扣

2.问题分析

我们根据 inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]来分析如何手动构建一颗二叉树

树的中序遍历与后序遍历和前边那个构建二叉树还是有稍微的不同的,但是大体思路是一致的.

中序和后序需要根据后序遍历来选取根结点,根结点是子树结点范围中的最后一个,例如postorder = [9,15,7,20,3]的根结点是最后一个{3};并且代码实现index从后向前遍历,先构建的右子树

① 首先根据后序遍历的特点,通过postorder我们可知3为根结点,再根据中序遍历的特点,通过inorder 我们可知3为根结点的左子树有{9},右子树有{15,20,7}这些元素

② 因为已经划分了左右子树,再看postorder,此时9为结点3左子树的根结点,20为结点3右子树的根结点,再看inorder ,此时左子树已经完成,结点20的左子树有{15},右子树有{7};

③ 因为已经划分了左右子树,再看preorder,此时15为结点20左子树的根结点,20为结点3右子树的根结点,,此时preorder数组已经遍历完毕,整棵树也已经构建完毕了 

由上面可以看出中序和后序构建二叉树和前序和中序构建二叉树的思路是一样的,实现也是一样的,代码递归构建却有很大的不同,代码递归实现和我们手动实现的顺序不一样,我们是同时寻找左右子树,递归是构建根结点,然后构建好右子树,最后构建左子树,直到全部遍历完成.(按照中右左的方式)

 

 

 其实不加    if(index==preorder.length)return null; 判断也没有错,只不过加上更加直观

3.代码实现

    Map<Integer, Integer> map = new HashMap<>();

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        for (int i = 0; i < inorder.length; ++i) {
            map.put(inorder[i], i);
        }
        index = postorder.length - 1;
        return findNode(inorder, postorder, 0, inorder.length - 1);

    }

    //这个index是postOrder的index
    int index;

    public TreeNode findNode(int[] inorder, int[] postorder, int left, int right) {
        if (index < 0) {
            return null;
        }
        if (left > right) {
            return null;
        }
        //1.从postorder找到根结点
        int val = postorder[index--];
        TreeNode root = new TreeNode(val);
        //2.从inorder找到左右子树
        Integer mid = map.get(val);
        //3.递归左子树
        root.right = findNode(inorder, postorder, mid+1, right);
        //4.递归右子树
        root.left = findNode(inorder, postorder, left, mid-1);

        return root;

    }

三.问题思考

现在我们思考这样一个问题:我们是否可以根据前序和后序遍历的顺序,来构建一颗二叉树呢?

答案是不行的,我们观察前面两个题目可以知道:我们最关键的在于寻找根结点,并找到它的左子树的结点范围和右子树结点范围,但是根据前序和后序遍历,第一次我们可以找到根结点,但是我们无法判断它的左子树是哪些,右子树是哪些,因此无法根据这两种遍历方式构建一颗二叉树

有关树的前序遍历与中序遍历构造二叉树和树的中序遍历与后序遍历构造二叉树的更多相关文章

  1. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  2. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  3. ruby - Chef Ruby 遍历 .erb 模板文件中的属性 - 2

    所以这可能有点令人困惑,但请耐心等待。简而言之,我想遍历具有特定键值的所有属性,然后如果值不为空,则将它们插入到模板中。这是我的代码:属性:#===DefaultfileConfigurations#default['elasticsearch']['default']['ES_USER']=''default['elasticsearch']['default']['ES_GROUP']=''default['elasticsearch']['default']['ES_HEAP_SIZE']=''default['elasticsearch']['default']['MAX_OP

  4. ruby - 如何遍历 Ruby 中所有正则表达式匹配的字符串? - 2

    我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby​​-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/

  5. ruby - 在 Ruby 中实现二叉树 - 2

    我一直在尝试在Ruby中实现BinaryTree类,但我得到了stackleveltoodeep错误,尽管我似乎没有在该特定代码段中使用任何递归:1.classBinaryTree2.includeEnumerable3.4.attr_accessor:value5.6.definitialize(value=nil)7.@value=value8.@left=BinaryTree.new#stackleveltoodeephere9.@right=BinaryTree.new#andhere10.end11.12.defempty?13.(self.value==nil)?true:

  6. ruby-on-rails - 在 Rails 中需要整个目录树的好方法是什么? - 2

    我正在使用Rails3.2.2并希望递归加载某个目录中的所有代码。例如:[Railsroot]/lib/my_lib/my_lib.rb[Railsroot]/lib/my_lib/subdir/support_file_00.rb[Railsroot]/lib/my_lib/subdir/support_file_01.rb...基于谷歌搜索,我试过:config.autoload_paths+=["#{Rails.root.to_s}/lib/my_lib/**"]config.autoload_paths+=["#{Rails.root.to_s}/lib/my_lib/**/"

  7. ruby - 循环遍历数组的元素 - 2

    我想从0到2循环@a:0,1,2,0,1,2。defset_aif@a==2@a=0else@a=@a+1endend也许有更好的方法? 最佳答案 (0..2).cycle(3){|x|putsx}#=>0,1,2,0,1,2,0,1,2item=[0,1,2].cycle.eachitem.next#=>0item.next#=>1item.next#=>2item.next#=>0... 关于ruby-循环遍历数组的元素,我们在StackOverflow上找到一个类似的问题:

  8. ruby-on-rails - 如何在 Rails View 中遍历数组? - 2

    我在MySql中进行了查询,但在Rails和mysql2gem中工作。信息如下:http://sqlfiddle.com/#!2/9adb8/6查询工作正常,没有问题,并显示以下结果:UNITV1A1N1V2A2N2V3A3N3V4A4N4V5A5N5LIFE200120000000000ROB010012000000000-为rails2.3.8安装了mysql2gemgeminstallmysql2-v0.2.6-创建Controller:classPolicyController这是日志:SQL(0.9ms)selectdistinct@sql:=concat('SELECTpb

  9. ruby - Ruby 中的目录遍历 - 2

    我一直在尝试使用简单的递归方法在Ruby中为一个更大的程序的一部分实现目录遍历。但是我发现Dir.foreach不包括其中的目录。我怎样才能列出它们?代码:defwalk(start)Dir.foreach(start)do|x|ifx=="."orx==".."nextelsifFile.directory?(x)walk(x)elseputsxendendend 最佳答案 问题是每次递归,你传递给File.directory?的路径isno只是实体(文件或目录)名称;所有上下文都丢失了。所以说你进入one/two/three/检

  10. ruby - 我如何从 Rational(或任何没有构造函数的类)继承? - 2

    例如,我可以很容易地继承自String,如下所示:classMyString'thingsandstuff'但是我如何继承没有构造函数的Rational呢?例如:defMyRatNoMethodError:undefinedmethod`new'forMyRat:ClassMyRat(10).inc#=>NoMethodError:undefinedmethod`MyRat'formain:ObjectMyRat.send(:initialize,10).inc#=>TypeError:alreadyinitializedclass#???#Noneofitworks!我找不到初始化新

随机推荐