目录

一、知识铺垫

二、二叉树的创建之递归

三、二叉树的创建之非递归(迭代)


初学者对于二叉树的遍历(前序遍历,中序遍历,后序遍历,层序遍历),这些放在最早学习的内容,应该是非常熟悉的,但是渐渐的就会发现,对于如何创建一颗二叉树,初学者对此过程还不甚清晰。直接一个一个结点插入吗?当树的深度过大时,这显然是一个费时费力的过程。以下我们介绍二叉树的创建的两种方法——递归与非递归。

一、知识铺垫

创建任意一颗树,在不知道null值归属于哪个结点时,仅仅依靠 单独的遍历字符串 是没有办法把一棵树创建好的。

例如:当我们不知道null值归属与哪个结点时,则说明我们可以往遍历中的任意位置插入结点。

层序遍历:3,9,null,null,20,15,7

层序遍历:3,9,null,20,null,15,7

所以我们直到了单独的一种不知道null结点的遍历时无法准确创建出一棵树的,从遍历的特性我们可以知道,前序和后序可以确认根结点,中序可以确认左右子树,当我们要创建树时(遍历字符串中无null值),至少应该满足以下特性:

  1. 至少应提供两个以上的遍历字符串
  2. 一定要提供中序字符串

        当然,当遍历字符串中带了null值时,任意一种遍历字符串均能准确建树,我们这里讨论不带null值的情况。

二、二叉树的创建之递归

例:当前序遍历以及中序遍历已经被提供时。

前序:A B K M N O P L C D E F H I J G

中序:M N P O K L B A E D H I J F G C

最终树的图像:

代码:

public TreeNode root;public BinaryTree(String preOrder,String inOrder){root=createBinaryTreeByRecursive(preOrder,inOrder);}private TreeNode createBinaryTreeByRecursive(String preOrder,String inOrder){return create(preOrder,inOrder,0,inOrder.length()-1);}private int index=0;//千万注意preOder的下标要放在递归函数外边,因为其不能回退private BinaryTree.TreeNode create(String preOrder, String inOrder, int left, int right){if(left>right){return null;}//为每一个字符创建新的结点BinaryTree.TreeNode node=new BinaryTree.TreeNode(preOrder.charAt(index));
//可加可不加
//        if(left==right){
//            index++;
//            return node;
//        }int rootIndex=left-1;//记录根的下标//找到根结点在中序中的位置,以便确定左右子树for(int i=left;i<=right;i++){if(preOrder.charAt(index)==inOrder.charAt(i)){rootIndex=i;break;}}//在序列中找到了根节点的位置if(rootIndex>=left) {index++;}node.leftChild=create(preOrder,inOrder,left,rootIndex-1);node.rightChild=create(preOrder,inOrder,rootIndex+1,right);return node;}

同理,给定后序和中序即将从后往前遍历后序代码

也可以增加HashMap来减少搜索根节点的过程

三、二叉树的创建之非递归(迭代)

在明白和熟悉了递归创建二叉树后,我们可以开始着手非递归创建二叉树了。而最主要的就是把左子树与右子树的范围确认好,所以我们可以利用栈,来判定其接下来是建左子树还是右子树。

代码:

private TreeNode createBinaryTreeByStack(String preOrder,String inOrder){Stack<TreeNode> stack=new Stack<>();int inIndex=0;TreeNode root=new TreeNode(preOrder.charAt(0));stack.push(root);TreeNode cur=root;for(int i=1;i<preOrder.length();i++){if(stack.peek().val==inOrder.charAt(inIndex)){//判断哪些结点左子树已经建完while(!stack.empty()&&stack.peek().val==inOrder.charAt(inIndex)){cur= stack.pop();inIndex++;}cur.rightChild=new TreeNode(preOrder.charAt(i));stack.push(cur.rightChild);}else{//左子树没有走完,继续建左子树cur=stack.peek();cur.leftChild=new TreeNode(preOrder.charAt(i));stack.push(cur.leftChild);}}return root;}

时刻记住前序是根-左子树-右子树,而中序是左子树-根-右子树,所以栈中用来存储还未走右子树的根,当栈顶元素与中序中元素一致时,说明此节点的左子树已经走完了(建完了),要开始建右子树了,所以将其从栈中pop()出来,建立其右子树。

每一个结点都可以是根可以把前序和中序理解成是无数个根按照一定的顺序排列在一起,所以当前序的根与中序的根一致时,可以表明,这个结点,已经把中序的左子树-根当中的左子树建完了。

同理可得,当是后序左子树-右子树-根和中序左子树-根-右子树的时候,我们应该从后遍历后序字符串,同时从后遍历中序字符串,当后序字符串中的元素与中序字符串中的元素一致的时候,我们可以认为,这个结点,已经建完了其右子树,要开始建其左子树了,从而将此结点从栈中pop出。

可以做题练手:

LeetCode-105

二叉树的创建——递归与非递归相关推荐

  1. 二叉树创建及遍历算法(递归及非递归)(转)

    //二叉树处理头文件 //包括二叉树的结构定义,二叉树的创建,遍历算法(递归及非递归), /* 作者:成晓旭 时间:2001年10月7日(18:49:38-20:00:00) 内容:完成二叉树创建,二 ...

  2. 遍历二叉树的各种操作(非递归遍历)

    先使用先序的方法建立一棵二叉树,然后分别使用递归与非递归的方法实现前序.中序.后序遍历二叉树,并使用了两种方法来进行层次遍历二叉树,一种方法就是使用STL中的queue,另外一种方法就是定义了一个数组 ...

  3. 二叉树路径应用举例(基于非递归后序遍历)

    #include "stdafx.h" #include <iostream> #include <fstream>using namespace std; ...

  4. 转载:二叉树的前中后和层序遍历详细图解(递归和非递归写法)

    二叉树的前中后和层序遍历详细图解(递归和非递归写法) Monster_ii 2018-08-27 17:01:53 50530 收藏 403 分类专栏: 数据结构拾遗 文章标签: 二叉树 前序 中序 ...

  5. 二叉树的遍历-递归与非递归 - 海子

    二叉树的遍历-递归与非递归 二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就是递归定义,因此采用递归的方 ...

  6. 二叉树的先中后序递归和非递归遍历(数据结构作业)

    一.设计思想 我创建二叉树是用的先序创建,其中用'#'代表空节点. 1.递归先序遍历 (1)如果当前节点为空节点(用'#'代表空节点),结束当前函数 (2)打印当前节点 (2)递归当前节点的左子树 ( ...

  7. 【Java数据结构】二叉树的前中后序遍历(递归和非递归)

    二叉树的遍历 递归做法 前序遍历 中序遍历 后序遍历 非递归 前序遍历 中序遍历 后序遍历 二叉树遍历是二叉树的一种重要操作 必须要掌握 二叉树的遍历可以用递归和非递归两种做法来实现 递归做法 前序遍 ...

  8. 实验五 二叉树的递归及非递归的遍历及其应用

    实验目的 熟练掌握二叉树的二叉链表存储结构的C语言实现.掌握二叉树的基本操作-前序.中序.后序遍历二叉树的三种方法.了解非递归遍历过程中"栈"的作用和状态,而且能灵活运用遍历算法实 ...

  9. python创建树结构、求深度_数据结构-树以及深度、广度优先遍历(递归和非递归,python实现)...

    前面我们介绍了队列.堆栈.链表,你亲自动手实践了吗?今天我们来到了树的部分,树在数据结构中是非常重要的一部分,树的应用有很多很多,树的种类也有很多很多,今天我们就先来创建一个普通的树.其他各种各样的树 ...

最新文章

  1. 不同硬件协议类型,相同的理解思路
  2. 自动化Debias框架,一键去除推荐系统所有Bias
  3. javascript 中 split 函数分割字符串成数组
  4. Cloud Insight 客户案例-晨芯时代科技有限公司
  5. IT真的很重要,还是会被边缘化?
  6. Couldn't find leader offsets for Set([smt,0], [smt,1], [smt,2])
  7. 两个时间相差距离多少小时 (精确到秒)
  8. 超越JUnit –测试框架的替代方案
  9. n个节点的二叉树n+1_使用C ++程序删除链接列表的M个节点后的N个节点
  10. 22.敏捷估计与规划——Why Agile Planning Works笔记
  11. java英文单词单复数转换
  12. android wifi设备连接通信,通过wifi与设备进行通信(Android)
  13. jQuery怎么改变img的src
  14. win10设置pg/pc接口_旧电脑升级!使用固态硬盘必做的5件事,让win10操作流畅如win7...
  15. taskfactory默认执行慢的问题
  16. Atitit 信息化建设纲要 艾提拉著
  17. word文档解除编辑受限(忘记密码)
  18. WIN10 拨号连接下 如何开启移动热点
  19. win10的服务器管理器在哪打开?
  20. 京东商城空调标价0元引发抢购

热门文章

  1. web端上传图片的几种方式
  2. kicad最小布线宽度默认是多少_CABLExpress发布了最新的光纤布线最佳实践指南
  3. asp生成带参数的二维码并合成推广海报图片,asp合并合成推广海报图片asp代码
  4. tmux命令启动MySQL_程序后台运行的几种方法
  5. 2023年长沙Java培训机构排名前十新鲜出炉!有你心仪的机构吗?
  6. 2021 csp-s
  7. 【搭建方案】国标GB28181视频平台EasyGBS流媒体服务器如何实现小区安防监控系统的网页直播?
  8. Linux中使用grep -v grep 查找不含有 grep 字段的行
  9. #千锋逆战班,王富胜# 学如逆水行舟,不进则退。在千锋学习的第14天 笔记整理
  10. oracle pga的作用,Oracle PGA作用