前序遍历

思路:
前序遍历就是先遍历一棵树的根节点,然后遍历左子树,再遍历右子树。要用非递归实现前序遍历,我们首先需要定义一个栈,再定义一个cur引用指向根节点。
只要cur不为空,就打印出cur的值,并且将cur指向的节点入栈。

cur引用一直向左走,直到走到null。
然后将栈顶元素出栈,cur指向栈顶元素的右子树,如果cur为空,就接着出栈下一个栈顶元素,再去判断它的右子树是否为空,不为空的话就重复上面的打印和入栈操作,直到栈为空。
实现代码如下:

private static void preOrderNoR(TreeNode root){TreeNode cur = root;Stack<TreeNode> stack = new Stack<>();while (!stack.empty() || cur!=null){//优先走左边while (cur!=null){//第一次遇到cur这个节点的位置System.out.print(cur.val);stack.push(cur);cur = cur.left;}//向左走到头了需要回溯//从栈里取出节点进行回溯//目前栈里的所有节点的右子树都没有进行遍历TreeNode top = stack.pop();cur = top.right;}}

中序遍历

思路:
中序遍历是先遍历左子树,然后根节点,最后遍历右子树。和上面操作一样的是需要借助栈来完成。
cur先指向根节点,只要cur不为空,就先入栈,然后一直向左走,走到头之后将栈顶元素出栈,打印栈顶元素的值并且将cur指向栈顶元素的右子树,为空的话就出栈下一个栈顶元素并打印,cur再指向刚刚出掉的那个节点的右子树,不为空的话就重复上面入栈的操作,直到栈为空。

还是用这棵树来说,从根节点一直向左走,4的左子树为空,将4出栈并打印,然后去遍历4的右子树,也为空,所以接着将下一个栈顶元素2出栈并打印,遍历2的右子树,不为空,将5入栈。

判断5的左子树为空,所以将栈顶元素5出栈并打印,5的右子树也为空,继续将栈顶元素1出栈并打印,遍历1的右子树,不为空,所以3入栈,3的左子树也不为空,6入栈,然后重复上面的操作就可以得到中序遍历的结果。

具体实现代码如下:

private static void inOrderNoR(TreeNode root){TreeNode cur = root;Stack<TreeNode> stack = new Stack<>();while (!stack.empty() || cur!=null){//优先走左边while (cur!=null){//第一次遇到cur这个节点的位置stack.push(cur);cur = cur.left;}//向左走到头了需要回溯//从栈里取出节点进行回溯//目前栈里的所有节点的右子树都没有进行遍历TreeNode top = stack.pop();//top取出的节点,是第二次遇到该节点System.out.print(top.val);cur = top.right;}}

后序遍历

思路:
后序遍历的非递归实现相对复杂,需要考虑的情况比较多。先遍历左子树,再遍历右子树,最后打印根节点。
首先我们还是定义一个栈和一个引用cur指向根节点,再定义一个last引用,用来保存上一次被完整后序遍历过的树的根节点。
将cur引用走到左子树的尽头,然后查看栈顶元素,只要它的右子树不为空,就将cur引用指向它的右子树,如果cur不为空就重复入栈的操作。
而如果栈顶元素的右子树为空或者是已经被遍历过的根节点,就直接将这个栈顶元素打印并出栈,更改last引用的指向,直到栈为空。
用具体例子来说就是:
和中序遍历一样,cur引用只要不为空就入栈并且一直向左走。

走到头之后查看栈顶元素为4,4的右子树为空,所以打印4并且将4出栈,last引用指向4,表示4是之前已经遍历过的根节点。
虽然现在cur为空,但是当前栈并不为空,所以接着查看栈顶元素2,2的右子树不为空,也不是上次已经遍历过的根节点,所以要去遍历2的右子树。

2的右子树为5,所以要进行入栈操作,5的左子树为空,右子树也为空,所以将5打印并出栈,更改last引用的指向。

接着查看栈顶元素为2,2的右子树不为空,但是等于上次已经遍历过的根节点,也就是last引用指向的节点,所以直接打印并出栈,再次更改last引用的指向。

一直重复上述步骤,直到栈为空,就可以得到后序遍历的结果,代码如下:

private static void postOrderNoR(TreeNode root){TreeNode cur = root;TreeNode last = null;       //上一次被完整后序遍历过的树的根节点Stack<TreeNode> stack = new Stack<>();while (!stack.empty() || cur!=null){//优先走左边while (cur!=null){//第一次遇到cur这个节点的位置stack.push(cur);cur = cur.left;}//向左走到头了需要回溯//从栈里取出节点进行回溯//目前栈里的所有节点的右子树都没有进行遍历TreeNode top = stack.peek();if (top.right==null){System.out.print(top.val);stack.pop();last = top;}else if (top.right==last){System.out.print(top.val);stack.pop();last = top;}else {cur = top.right;}}}

非递归实现二叉树的遍历相关推荐

  1. 后序遍历的非递归算法python_刷题系列 - Python用非递归实现二叉树后续遍历

    顺便把Python用非递归实现二叉树后续遍历也写了. 其实前序中序和后续都是针对父节点说的.比如下面这个最简单二叉树. 前序就是ABC,父节点A在前 中序就是BAC,父节点A在中间 后序就是BCA,父 ...

  2. 二叉树层序遍历递归与非递归_二叉树的遍历「递归、非递归」以及自己的感受

    --------又来了一次二叉树的遍历,每次都有不一样的理解!真不知道那些大佬是如何想出这些牛逼的算法的,佩服至极!!!!大家多写,多想,对这些的理解真的会发生变化!!! -------- ----- ...

  3. 二叉树的遍历:先序 中序 后序遍历的递归与非递归实现及层序遍历

    二叉树的定义:一种基本的数据结构,是一种每个节点的儿子数目都不多于2的树 树节点的定义如下: // 树(节点)定义 struct TreeNode {int data; // 值TreeNode* l ...

  4. 二叉树的层序遍历,前序遍历(递归,非递归),中序遍历(递归,非递归),后续遍历(递归,非递归)

    文章目录 二叉树的层序遍历 前序遍历 递归版本 非递归版本 中序遍历 递归版本 非递归版本 后序遍历 递归版本 非递归版本 二叉树的层序遍历 void printTree(BinaryTree* ar ...

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

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

  6. 二叉树前中后序遍历的非递归实现以及层次遍历、zig-zag型遍历详解

    前言 二叉树的遍历是一个比较常见的问题,递归实现二叉树的前中后序遍历比较简单,但非递归实现二叉树的前中后序遍历相对有难度.这篇博客将详述如何使用非递归的方式实现二叉树的前中后序遍历,在进行理论描述的同 ...

  7. 非递归实现二叉树结点的遍历

    非递归实现二叉树结点的遍历 考研复习时遇到了二叉树遍历的考点,于是把它按照自己的思路整理出来,可能存在些许错误 ,但大致思想应该没问题. 1.先序遍历 思想:先序遍历的处理顺序是根.左.右,如果我们把 ...

  8. 非递归实现二叉树的前序、中序、后序遍历

    目录 非递归实现二叉树的前序遍历 非递归实现二叉树的中序遍历 非递归实现二叉树的后序遍历 根据二叉树的前序和中序遍历结果还原二叉树 根据二叉树的中序和后序遍历结果还原二叉树 非递归遍历需要借助栈. 非 ...

  9. python非递归前序遍历二叉树_Python非递归实现二叉树的后续遍历

    leetcode 145. Binary Tree Postorder Traversal 思路一: 使用一个栈stack保存经过的根结点,另一个栈flag保存每个结点的右子树是否遍历: 如果根结点存 ...

最新文章

  1. 20165203《Java程序设计》第二周Java学习总结
  2. ansible1.7.2源码安装教程
  3. 【Linux】一步一步学Linux——Unix发展史(02)
  4. CF1119H-Triple【FWT】
  5. 2016蓝桥杯省赛---java---C---10(密码脱落)
  6. sql 计算两个小数乘积_数学篇|学会这些数学计算技巧,想不满分都难!
  7. 为什么Vue不能观察到数组length的变化?
  8. 阿里云 mysql 双主_mysql数据库一主两从
  9. pandas keyerror: 标签_Hinton新作!越大的自监督模型,半监督学习需要的标签越少...
  10. POJ 1113 Wall 求凸包
  11. 0基础学python要多久-27岁0基础自学Python,多久可以找到工作?
  12. 如何在java中实现小数点自增_java保留小数的四种实现方法
  13. 通过lan从服务器启动系统,OPNsense启用LAN网桥
  14. 中心极限定理 与 正态分布
  15. (Python3) Numeric (数字)类型
  16. 面试技巧STAR原则
  17. 数位dp BZOJ 2757: [SCOI2012]Blinker的仰慕者
  18. 《大话设计模式》—— 读后感 (12)牛市股票还会亏钱?—— 外观模式
  19. fputc函数重写实现printf重定向
  20. 最常见的运放LM358简要功能介绍(抄原理图)

热门文章

  1. html中字段间距代码,css调字体大小代码 css字与字之间的间距怎么调
  2. NTP调整系统时间同步
  3. Arch Linux上使用 pandoc 将 markdown 转为 pdf 以及如何查看本机的中文字体 fc-list :lang=zh
  4. linux 端口耗尽,解决端口耗尽问题: tcp_tw_reuse、tcp_timestamps
  5. 阿木社区的SLAM无人机硬件配置
  6. Android模拟屏幕鼠标
  7. 数据库查询语句(书上例题)
  8. Kali之Crunch:自定义字典
  9. 卸载VS时彻底删除C盘文件方法
  10. Windows应用程序设计