本文主要介绍二叉树前序中序后序遍历的非递归写法

在探讨如何写出二叉树的前序中序后序遍历代码之前,我们先来明确一个问题,前序中序后序遍历根据什么区分

二叉树的前序中序后序遍历,是相较根节点说的。最先遍历根节点即为前序遍历,第二遍历根节点即为中序遍历,最后遍历根节点为后序遍历。左右节点的遍历顺序都是先左后右。

明确了上述之后,我们再来看一下如何定义树节点这一数据结构,新建树节点类,其具有值,左子树指针,右子树指针三种属性,加上构造方法后定义出来的结构如下:

    // 树结构public class TreeNode{int val;TreeNode left;TreeNode right;public TreeNode(){}public TreeNode(int val, TreeNode left, TreeNode right) {this.val = val;this.left = left;this.right = right;}}

明确了上述之后,让我们来一起看下二叉树前序遍历、中序遍历、后序遍历的非递归写法吧

1. 前序遍历

我们都知道递归底层是用栈来操作,那我们的非递归写法也就是使用栈模拟出二叉树遍历的操作。前序遍历使用栈模拟的操作过程如下:

每次执行的操作为:根节点出栈,节点值加入结果数组,然后将根节点右子节点入栈,再将根节点左子节点入栈。循环往复,直至栈为空。

先操作根节点值我们大家都能理解,那为什么是右子节点先入栈,然后左子节点后入栈那?

栈的操作为先进后出,因此先入栈的右子节点后出栈,后入栈的左子节点先出栈,这样得到的遍历顺序就为 —— 中 、左、右,因此要先入栈右子节点,后入栈左子节点。

代码:

    // 二叉树先序遍历迭代写法public List<Integer> preorderTraversal(TreeNode root){// 存储遍历结果List<Integer> ansList = new ArrayList<>();if(root == null){ // 树为空情况处理return ansList;}// 用于模拟操作的栈Stack<TreeNode> stack = new Stack<>();// 初始化放入根节点stack.push(root);while(!stack.isEmpty()){// 先序遍历先处理根节点TreeNode node = stack.pop();ansList.add(node.val);// 加入右节点 —— 先加入右节点后加入左节点 —— 从而保证出栈顺序为先左再右if(node.right != null) stack.push(node.right);// 加入左节点if(node.left != null) stack.push(node.left);}return ansList;}

2. 后序遍历

如果你理解了二叉前序遍历的非递归写法,那么后序遍历的非递归写法,就可以很快写出了。我们来思考一下前序遍历和后序遍历的关系。前序遍历的遍历顺序为 中左右,我们将其结果翻转一下就变成了 右左中,而后序遍历的顺序为 左右中,因此只需要把前序遍历的代码稍微调整一下左右子节点入栈的顺序,最后再把结果数组翻转就能得到后序遍历的写法了。具体操作为左节点先入栈,右节点后入栈(与我们在前序遍历中的入栈顺序正好相反),最后再使用 Collections.reverse() API 将结果List 翻转。

代码:

    // 后序遍历迭代写法 —— 思考其和前序遍历的不同 —— 前序遍历是 中左右  , 将其变为 中右左 ,再翻转最后的结果数组就变为 左右中 ,刚刚好是后序遍历的结果public List<Integer> postorderTraversal(TreeNode root) {List<Integer> ansList = new ArrayList<>();if(root == null){return ansList;}Stack<TreeNode> stack = new Stack<>();stack.push(root);while(!stack.isEmpty()){ // 出栈顺序为 中右左TreeNode node = stack.pop();ansList.add(node.val);if(node.left != null) stack.push(node.left);if(node.right != null) stack.push(node.right);}Collections.reverse(ansList); // 翻转链表return ansList;}

3. 中序遍历

前序遍历之所以看起来简单,是因为其操作的节点和其遍历顺序相同。而对中序遍历我们的模拟方法为:先一直沿左子树遍历,将沿途的节点入栈,直到遍历到最左叶子节点,这时就可以开始我们的操作了,操作方法为将最左叶子节点出栈进行操作,然后将右子节点入栈,右子节点重复执行上述过程(即找到右子节点的最左子节点…省略重复过程…)。

具体到代码: 因为不是最先遍历root 节点了,因此不需要先在 stack 中加入 root。而是使用一 cur 节点记录当前遍历的节点,开始的时候 cur 一直向左找,直到找到第一个要操作的节点,cur 和 stack 其中一个不为空就继续遍历。

代码:

   // 二叉树中序遍历迭代写法public List<Integer> inorderTraversal(TreeNode root) {// 存储遍历结果List<Integer> ansList = new ArrayList<>();if(root == null){ // 树为空情况处理return ansList;}// 用于模拟操作的栈Stack<TreeNode> stack = new Stack<>();/********** 上述内容所有遍历都一样 ************/TreeNode cur = root;while(cur!=null || !stack.isEmpty()){if(cur != null){ // 一直放左子节点,直到找到要处理的第一个左子节点stack.push(cur);cur = cur.left; // 将当前遍历节点变为左子节点} else{ // 到达要处理的位置TreeNode node = stack.pop();ansList.add(node.val); // 处理根节点 —— 先处理根节点,然后就加入右叶子节点cur = node.right; // 将当前遍历节点改为右子节点}}return ansList;}

【二叉树Java】二叉树遍历前序中序后序遍历的非递归写法相关推荐

  1. Python__数据结构与算法——树、二叉树(实现先、中、后序遍历)

    目录 一.树 二.二叉树 树和前面所讲的表.堆栈和队列等这些线性数据结构不同,树不是线性的.在处理较多数据时,使用线性结构较慢,而使用树结构则可以提高处理速度.不过,相对于线性的表.堆栈和队列等线性数 ...

  2. 二叉树的前序中序后序遍历java代码实现

    1.前序遍历概述 前序遍历(VLR) 是二叉树遍历的一种,也叫做先根遍历.先序遍历.前序周游,可记做根左右.前序遍历首先访问根结点然后遍历左子树,最后遍历右子树. 若二叉树为空则结束返回,否则: (1 ...

  3. 二叉树遍历(递归实现前序/中序/后序遍历)

    1. 准备工作 我们先定义一棵普通的二叉树,如下图 2. 前序遍历 通过递归进行遍历: 如果二叉树为空,则操作返回: 如果非空,否则从根结点开始,然后遍历左子树,再遍历右子树. 前序遍历的结果是:AB ...

  4. 二叉树前序、中序、后序遍历非递归写法的透彻解析

    前言 在前两篇文章二叉树和二叉搜索树中已经涉及到了二叉树的三种遍历.递归写法,只要理解思想,几行代码.可是非递归写法却很不容易.这里特地总结下,透彻解析它们的非递归写法.其中,中序遍历的非递归写法最简 ...

  5. java中二叉树_Java工程师面试1000题224-递归非递归实现二叉树前、中、后序遍历...

    224.使用递归和非递归实现二叉树的前.中.后序遍历 使用递归来实现二叉树的前.中.后序遍历比较简单,直接给出代码,我们重点讨论非递归的实现. class Node { public int valu ...

  6. 二叉树前序遍历python输出_[宜配屋]听图阁 - Python实现输入二叉树的先序和中序遍历,再输出后序遍历操作示例...

    本文实例讲述了Python实现输入二叉树的先序和中序遍历,再输出后序遍历操作.分享给大家供大家参考,具体如下: 实现一个功能: 输入:一颗二叉树的先序和中序遍历 输出:后续遍历 思想: 先序遍历中,第 ...

  7. 二叉树的前序中序后序遍历

    二叉树的前序中序后序遍历 二叉树的遍历 前序遍历 中序遍历 后序遍历 总结 二叉树的遍历 二叉树的遍历有前序遍历,中序遍历,后序遍历三种. 今天我把二叉树的遍历方法给大家总结一下,也算对我自己学习的一 ...

  8. 二叉树的前序、中序、后序遍历(递归、非递归写法)

    文章目录 一.什么是二叉树? 二.二叉树的基本概念 三.二叉树的三种遍历方式 1.前序遍历(preordertraversal) 1.中序遍历(inordertraversal) 1.后序遍历(pos ...

  9. 二叉树的前序中序后序遍历真题

    一颗二叉树的前序遍历是ABCDFGHE,后序遍历是BGHFDECA,中序遍历是? A.GHBADFCEB.DGBAFHECC.BADGFHCED.BAGDFHEC 正确答案:C 牛客网来源:https ...

最新文章

  1. android绘制心形_Android自定义View系列(一)——打造一个爱心进度条
  2. 全球机器学习领域顶尖的16家公司
  3. yii2权限控制rbac之rule详细讲解(转)
  4. 一条龙奇迹私服WEB系统后门及bug
  5. python中的super用法详解_【Python】【类】super用法详解
  6. java消息头,Java网络编程从入门到精通:HTTP消息头字段
  7. .h .dll .lib
  8. JAVA实现把指定文件夹下的所有文件压缩成zip包
  9. Pragma是什么?
  10. Centos yum install和yum groupinstall的区别
  11. This application is only supported on Windows 8.1, Windows Server 2012 R2, or hi gher.
  12. 全面提升AI语言理解能力,达摩院自研语言模型体系登顶6大权威榜单
  13. 快手面试官:Redis变慢了,如何快速排查?
  14. 暨反欺诈建模场景实操
  15. 《机器学习》(周志华)学习笔记
  16. ExtJS界面设计工具 Ext Designer
  17. linux静态路由表无故消失,探究几种静态路由的行为及自动删除行为
  18. server2003 必要的系统优化和安全设置
  19. 从P1到P7——我在淘宝这7年
  20. 【Spring源码三千问】Bean的Scope有哪些?scope=request是什么原理?

热门文章

  1. 用户数据分析案例学习笔记
  2. FPGA学习——基本结构
  3. 中国广电确定与一家运营商共建共享,电信?移动?联通?
  4. CVPR2020-Reverse Perspective Network for Perspective-Aware Object Counting:透视感知目标计数的反向透视网络
  5. python airflow_airflow 实战总结
  6. 深度学习-视频行为识别:论文阅读——双流网络(Two-stream convolutional networks for action recognition in videos)
  7. 网站服务器Win2003系统网络安全设置全攻略
  8. java 轮询请求_使用RxJava来实现网络请求轮询功能
  9. LTE中小区选择流程及其S准则详解
  10. Shell万能工具箱脚本