一、递归法

这次我们要好好谈一谈递归,为什么很多同学看递归算法都是“一看就会,一写就废”。

主要是对递归不成体系,没有方法论,每次写递归算法 ,都是靠玄学来写代码,代码能不能编过都靠运气。

本篇将介绍前后中序的递归写法,一些同学可能会感觉很简单,其实不然,我们要通过简单题目把方法论确定下来,有了方法论,后面才能应付复杂的递归。

这里帮助大家确定下来递归算法的三个要素。每次写递归,都按照这三要素来写,可以保证大家写出正确的递归算法!

1.确定递归函数的参数和返回值:
确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。

2.确定终止条件:
写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。

3.确定单层递归的逻辑:
确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

以下以前序遍历为例:

**确定递归函数的参数和返回值:**因为要打印出前序遍历节点的数值,所以参数里需要传入vector在放节点的数值,除了这一点就不需要在处理什么数据了也不需要有返回值,所以递归函数返回类型就是void,代码如下:

void traversal(TreeNode cur, vector& vec)*
**确定终止条件:**在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要要结束了,所以如果当前遍历的这个节点是空,就直接return,代码如下:

if (cur == NULL) return;
**确定单层递归的逻辑:**前序遍历是中左右的循序,所以在单层递归的逻辑,是要先取中节点的数值,代码如下:

vec.push_back(cur->val); // 中
traversal(cur->left, vec); // 左
traversal(cur->right, vec); // 右

单层递归的逻辑就是按照中左右的顺序来处理的,这样二叉树的前序遍历,基本就写完了,在看一下完整代码:

二、先序遍历的递归写法

class Solution {public List<Integer> preorderTraversal(TreeNode root) {ArrayList<Integer> list = new ArrayList<>();preorder(root,list);return list;}private void preorder(TreeNode root,List<Integer> list){if(root == null){return;}list.add(root.val);preorder(root.left,list);preorder(root.right,list);}
}

三、先序遍历的非递归写法

class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> list = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();while(root != null || !stack.isEmpty()){while(root != null){list.add(root.val);stack.push(root);root = root.left;}TreeNode cur = stack.pop();root = cur.right;}return list;}
}

四、中序遍历的递归写法

class Solution {public List<Integer> inorderTraversal(TreeNode root) {ArrayList<Integer> list = new ArrayList<>();inorder(root,list);return list;}public void inorder(TreeNode root,List<Integer> list){if(root == null){return;}inorder(root.left,list);list.add(root.val);inorder(root.right,list);}
}

五、中序遍历的非递归写法

class Solution {public List<Integer> inorderTraversal(TreeNode root) {ArrayList<Integer> list = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();while(root != null || !stack.isEmpty()){while(root != null){stack.push(root);root = root.left;}root = stack.pop();list.add(root.val);root = root.right;}return list;}
}

六、后序遍历的递归写法

class Solution {public List<Integer> postorderTraversal(TreeNode root) {ArrayList<Integer> list = new ArrayList<>();postorder(root,list);return list;}private void postorder(TreeNode root,List<Integer> list){if(root == null){return;}postorder(root.left,list);postorder(root.right,list);list.add(root.val);}
}

七、后序遍历的非递归写法

class Solution {public List<Integer> postorderTraversal(TreeNode root) {ArrayList<Integer> list = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();while(root != null || !stack.isEmpty()){while(root != null){list.add(root.val);stack.push(root);root = root.right;}TreeNode cur = stack.pop();root = cur.left;}Collections.reverse(list);return list;}
}

4.二叉树的先序、中序以及后序遍历的递归写法与非递归写法(LeetCode第94、144、145题)相关推荐

  1. [Leedcode][JAVA][第94/144/145题][前中后序遍历][递归][迭代][二叉树]

    [问题描述][] 前序遍历 先输出当前结点的数据,再依次遍历输出左结点和右结点 中序遍历 先遍历输出左结点,再输出当前结点的数据,再遍历输出右结点 后续遍历 先遍历输出左结点,再遍历输出右结点,最后输 ...

  2. 算法练习day10——190328(二叉树的先序、 中序、 后序遍历, 包括递归方式和非递归方式、找到一个节点的后继节点、二叉树的序列化和反序列化)

    1.实现二叉树的先序. 中序. 后序遍历, 包括递归方式和非递归方式 1.1 访问节点的顺序 节点访问顺序如下图所示: 访问顺序:1 2 4 4 4 2 5 5 5 2 1 3 6 6 6 3 7 7 ...

  3. PAT甲级1020变体:已知二叉树层序+中序序列,求后序遍历序列

    PAT甲级1020变体:已知二叉树层序+中序序列,求后序遍历序列 题目 输入格式 输出格式 输入样例 输出样例 代码 题目 已知二叉树层序+中序序列,求后序遍历序列. 输入格式 第一行给出该二叉树的节 ...

  4. 二叉树中序遍历(递归法和迭代法(非递归法))——C++

    声明:本文原题主要来自力扣,记录此博客主要是为自己学习总结,不做任何商业等活动! 二叉树的遍历有前序遍历.中序遍历.后序遍历和层次遍历,其中二叉树基本知识点可以参考博主上篇博客(二叉树基本知识点图文介 ...

  5. 二叉树的中序、前序、后序三种遍历图解

    二叉树是算法中的重要概念,现将中序.前序.后序三种遍历图解如下: ***站里很多帖子讲到三种遍历的顺序是逐一开展的,但是我感觉同级遍历应该是同时开展的,不知道对不对,请大牛指教~~

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

    文章目录 一. 题目描述 二. 代码 & 思路 1. 递归的写法 2. 迭代的写法(本文重点来了) 1) 前序 2) 中序 3) 后序 直接来个整合吧,也方便看.之前只写了递归的,现在补上迭代 ...

  7. 先序中序数组推后序数组

    二叉树遍历 所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问.访问结点所做的操作依赖于具体的应用问 题. 遍历是二叉树上最重要的运算之一,是二叉树上进行其它 ...

  8. 已知满二叉树先序序列如何求后序序列

    如题 自用笔记 如有错误欢迎及时指正 面对仅仅知道先序序列(DLR)求后序序列(LRD),首先想到的是不可能,若对一般的二叉树而言确实无法做到,但是满二叉树的特殊性使得该命题成立!下面给出本文所用例子 ...

  9. 树的遍历(中序,前序,后序)

    与只有一种逻辑遍历它们的线性数据结构(数组.链表.队列.堆栈等)不同,树可以以不同的方式遍历,常见的有中序遍历,前序遍历和后序遍历. 实现各种遍历的方法又包括: 以上图为例: 深度优先遍历:  (a) ...

  10. 递归转化成非递归过程_8086微处理器中的递归和重入过程

    递归转化成非递归过程 As we all know that a procedure is a set of instruction written separately which can be u ...

最新文章

  1. docker部署springboot_Docker+SpringBoot快速构建和部署应用
  2. 全球半导体产业迁移 中国的机遇与挑战
  3. jQuery之动画效果
  4. 信息抽取(三)三元关系抽取——改良后的层叠式指针网络,让我的模型F1提升近4%(接上篇)
  5. 致毕业生:那些年我们错过的“BAT”
  6. @JsonProperty注解解析
  7. jdk并发包里常用的类
  8. 在ASP.NET使用javascript的一点小技巧(转www.chinacs.net 中文C#技术站 )
  9. java实时读取文件内容,java实时读取和写入文件
  10. android qq三方登录授权失败,qq第三方登陆授权失败110401错误码解决办法介绍
  11. C#如何实现 ASCII码与字母的互相转换?
  12. Window下MySQL 8.0重新设置密码
  13. 域名邮箱和邮件服务器
  14. 在PGConf.Asia-中文技术论坛,聆听腾讯云专家对数据库技术的深度理解
  15. mysql调整specified key_MySQL错误“Specified key was too long; max key length is 1000 bytes”的解决办法...
  16. 苹果的新技术3D Touch与以往的“长按屏幕”有何区别?
  17. 3P(PS、PR、PDF编辑器Acrobat)中的基基本操作(一)
  18. 为什么c语言加法错误,分数的加减法——C语言初学者代码中的常见错误与瑕疵(12)...
  19. ARCore之路-连接设备调试应用
  20. 【图像处理】相机成像原理

热门文章

  1. 深度学习之输入通道个数、卷积核通道个数,卷积核个数、输出通道个数的关系
  2. DeepChem | 基于DeepChem的GCN预测化合物溶解度
  3. Variant Analysis(变种分析)——使用已知漏洞发掘未知漏洞
  4. linux命令rname,linux的rename命令
  5. 取文字_取一个好听的女孩名字
  6. R语言绘制堆叠的环状条形图
  7. 分享|如何制作高质量的图文摘要(Graphical Abstract)
  8. The Innovation | Volume 2 Issue3 正式出版
  9. GM:「世界第一」SCI全文数据库,我做到了!
  10. 怎么跑都不累?自然医学揭秘微生物组提升运动表现