文章目录

  • 一. 题目描述
  • 二. 代码 & 思路
    • 1. 递归的写法
    • 2. 迭代的写法(本文重点来了)
      • 1) 前序
      • 2) 中序
      • 3) 后序

直接来个整合吧,也方便看。之前只写了递归的,现在补上迭代的(迭代才是考点!)
是面试高频题,要好好掌握好各自间的区分哦!

一. 题目描述

题目描述基本上一样,就只展示中序的题干了

二. 代码 & 思路

1. 递归的写法

  • 这里比较简单,就不赘述了,就是换换顺序。
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {List<Integer> ans = new ArrayList<>();public List<Integer> inorderTraversal(TreeNode root) {mid(ans);return ans;}// 前序void first(TreeNode root){if(root == null){return;}ans.add(root.val);first(root.left);first(root.right);}// 中序void mid(TreeNode now){if(now == null){return;}mid(now.left);ans.add(now.val);mid(now.right);}// 后序void last(TreeNode now){if(now == null){return;}last(now.left);last(now.right);ans.add(now.val);}
}

2. 迭代的写法(本文重点来了)

说实话,三份代码简直模版:while & if else & stack,写的前五行代码是一样的

  • 首先明确一点,栈的作用
  • 前面的递归写法,就是 JVM 隐式地帮我们进行了栈的操作
  • 迭代:用栈模仿虚拟机的调用过程
  • 前序 & 中序很像,后序相对难一点,需要维护一个 pre 结点
1) 前序
class Solution {List<Integer> ans = new ArrayList<>();public List<Integer> preorderTraversal(TreeNode root) {// 迭代:通过栈模拟虚拟机的递归结构Stack<TreeNode> myStack = new Stack<>();TreeNode now = root;// 前中后写的前五行代码都是一样的while(now != null || !myStack.isEmpty()){// 非null情况:先加再说!入栈,然后直接往左走if(now != null){ans.add(now.val);myStack.push(now);now = now.left;}// null情况:那就走父结点的右边!else {now = myStack.pop().right;}}return ans;}
}
2) 中序
  • 和前序相比,都是一路向左,到头了就取父结点的右边
  • 不同之处在于,ans.add的位置,前序 & 中序分布在 if else 中
class Solution {List<Integer> ans = new ArrayList<>();public List<Integer> inorderTraversal(TreeNode root) {// 迭代:用栈模仿虚拟机的调用过程Stack<TreeNode> myStack = new Stack<>();TreeNode now = root;// 结束条件:当前结点已经走到底,并且栈中也无可用结点了while(now != null || !myStack.isEmpty()){// 非null情况:入栈,一路向左if(now != null){myStack.push(now);now = now.left;}// null情况:左到头了,取出父节点,加入答案,然后从父结点的右结点继续else{TreeNode temp = myStack.pop();ans.add(temp.val);now = temp.right;}}return ans;}
}
3) 后序
  • 非null情况处理,和中序完全一样
  • 唯一一个使用了peek的,也就是说:null情况不一定会pop
  • 代码重点在于:null 情况部分,详细见代码
  • pre 的更新是从底向上的(有点抽象,结合代码可能比较好理解)
class Solution {List<Integer> ans = new ArrayList<>();public List<Integer> postorderTraversal(TreeNode root) {Stack<TreeNode> myStack = new Stack<>();TreeNode now = root;// 相对于前序 & 中序,此处加了个 pre 结点,用来验证右边结点是否走过TreeNode pre = null;while(now != null || !myStack.isEmpty()){// 非null情况:先 push 当前结点,然后往左冲!if(now != null){myStack.push(now);now = now.left;}// null情况:冲到头了else{// 注意这里是 peek,不一定 pop 掉now = myStack.peek();// 取答案的情况:父结点无右结点 Or 父节点的右结点已走过if(now.right == null || now.right == pre){ans.add(now.val);// 更新 pre 值为当前值,表示当前值已走过,供now的父节点使用pre = now;// pop 掉父节点myStack.pop();// 更新 now 为 null,下一次循环继续peeknow = null;}// 可以继续走右边的情况else{now = now.right;}}}return ans;}
}

【LeetCode笔记】94 144 145. 二叉树的前序、中序、后序遍历的迭代与递归(Java、dfs、迭代)相关推荐

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

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

  2. C++实现二叉树 前、中、后序遍历(递归与非递归)非递归实现过程最简洁版本

    本文并非我所写,是复制的该链接中的内容: 最近学习二叉树,想编程实现递归和非递归的实现方式: 递归的方式就不说了,因为大家的递归程序都一样:但是对于非递归的实现方式, 根据这几天的查阅资料已看到差不多 ...

  3. 【LeetCode | 二叉树前、中、后序遍历{迭代法}实现】

    1.前序遍历 // 解题思路:利用栈的原理实现以迭代方法来前序遍历(根左右)二叉树 class Solution { public:vector<int> preorderTraversa ...

  4. java数据结构学习笔记-二叉树前、中、后序遍历

    public class BinaryTreeDemo {public static void main(String args[]){Employee emp1= new Employee(1,&q ...

  5. 【LeetCode | 二叉树前、中、后序遍历{递归法}实现】

    1.前序遍历 #include <iostream> #include <vector> #include <queue> #include <algorit ...

  6. 二叉树前、中、后序线索化及遍历

    public class ThreadedBinaryTree {public static void main(String[] args){Heronodes node1=new Heronode ...

  7. 用前序中序创建二叉树(用中序后序创建二叉树)

    定义二叉树结点 比如就拿这个二叉树 前序中序创建 因为前序遍历的顺序是 根 , 左 ,右. 中序的遍历是 左 根 右. 我们会很不好想,但我们可以用前序和中序把上面那个二叉树的遍历一边 前序遍历:AB ...

  8. 栈的亚特兰数与二叉树的前序中序遍历序列

    栈的亚特兰数与二叉树的前序中序遍历 @(算法学习) 已经熟知的是二叉树的中序遍历和先序遍历可以唯一确定一棵树. 更有趣的知识点是,以先序遍历序列作为入栈序列,那么出栈序列恰为中序遍历.这样就把两种遍历 ...

  9. 二叉树的深度(前序 中序 后序 递归非递归搜素)、广度、搜索 C++

    a b c 使用 1 2 3 表示 /* 描述:二叉树的深度(前序 中序 后序 递归非递归搜素).广度.搜索 作者:jz 日期:20140819 */ #include<stdio.h> ...

最新文章

  1. RHCSA7-NOTE(红帽管理员-题库详细笔记)
  2. 洛谷 P1273 【有线电视网】
  3. html首字母样式,html标签手册
  4. 解决: IDEA 代码 commit 后,Local Changes 中代码依旧在,提交失败,报错:is out of date
  5. DDD 领域驱动设计落地实践:六步拆解 DDD
  6. 大学学python用记笔记吗_3年Python程序员平时学习笔记总结,对于学习Python非常有帮助!...
  7. 谷歌AI:根据视频生成深度图,效果堪比激光雷达
  8. WIN7下安装SVNserver端及client搭建协作环境
  9. python3.3使用tkinter实现猜数字游戏代码
  10. OSChina 周四乱弹 —— 有这个发现自己并不需要女朋友了
  11. 如何评估语音质量好坏?
  12. 软件工程实验二Visio的使用
  13. android+号码归属地数据库,Android手机号码归属地的查询
  14. 如何通过芯片手册寻找操作GPIO
  15. android判断图片是否模糊,Android 图片模糊 性能总结
  16. CTF PWN-攻防世界XCTF新手区WriteUp
  17. java freemarker转PDF和Word
  18. 微信小程序 - 二维码数据解析,如何扫码进入开发版测试二维码数据
  19. PMP学习笔记20161130
  20. mmap和shmget的区别

热门文章

  1. Python 程序 可以一直输入 quit_从零开始学Python - 第002课:第一个Python程序
  2. 软件测试知识产权保护,一种软件测试方法及软件测试系统专利_专利申请于2017-09-07_专利查询 - 天眼查...
  3. centos7调节虚拟机字体_初次安装虚拟机中Ubuntu16.04系统设置的一些小问题(小白教程)...
  4. OpenCV学习笔记(七):形态学morpholgy(1):腐蚀/膨胀:enrode(),dilate()
  5. VS2013中CUDA的配置
  6. dataframe常用操作总结
  7. MySQL索引原理、失效情况
  8. Python 的协程库 greenlet 和 gevent
  9. CompletableFuture详解~CompletionStage
  10. SpringBoot 自带工具类~StreamUtils