二叉树的遍历

先序

/**
* 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 {
static List<Integer> res; public List<Integer> preorderTraversal(TreeNode root) {
res = new ArrayList<>();
// preorderRecursion(root);
// preorder(root);
// preorderMorris(root);
// return res;
preorder3(root);
Collections.reverse(res);
return res;
} // 假先序
public static void preorder3(TreeNode root) {
if (root == null) return;
preorder3(root.right);
preorder3(root.left);
res.add(root.val);
} // 保存右节点
public static void perorder2(TreeNode root) {
if (root == null) return;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
res.add(cur.val);
if (cur.right != null) stack.push(cur.right);
if (cur.left != null) stack.push(cur.left);
}
} // Morris
public static void preorderMorris(TreeNode root) {
if (root == null) return; TreeNode cur = root; while (cur != null) {
if (cur.left != null) {
// 左子树不空,遍历左子树,找到左子树的最右侧节点
TreeNode rightMost = cur.left;
while (rightMost.right != null && rightMost.right != cur) {
rightMost = rightMost.right;
}
// 最右侧节点的右指针指向null或者cur
if (rightMost.right == null) {
// 有左右孩子的节点第一次被访问
res.add(cur.val);
// 把最右侧节点的right指向cur
rightMost.right = cur;
// 访问左子树
cur = cur.left;
} else {
// 有左右孩子的节点第二次被访问
// 恢复
rightMost.right = null;
// 遍历右子树
cur = cur.right;
}
} else {
// 只有右孩子的节点只会被访问一次
res.add(cur.val);
// 遍历右子树
cur = cur.right;
}
}
} // 非递归
public static void preorder(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
while (!stack.isEmpty() || root != null) {
while (root != null) {
res.add(root.val);
stack.add(root);
root = root.left;
}
root = stack.pop();
root = root.right;
}
} // 递归
public static void preorderRecursion(TreeNode root) {
if (root == null)
return;
res.add(root.val);
preorderRecursion(root.left);
preorderRecursion(root.right);
}
}

中序

/**
* 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 {
static List<Integer> res; public List<Integer> inorderTraversal(TreeNode root) {
res = new ArrayList<>();
// inorderRecursion(root);
// inorder(root);
inorderMorris(root);
return res;
} public static void inorderMorris(TreeNode root) {
if (root == null) return;
TreeNode cur = root;
while (cur != null) {
if (cur.left != null) {
TreeNode rightMost = cur.left;
while (rightMost.right != null && rightMost.right != cur) {
rightMost = rightMost.right;
}
if (rightMost.right == null) {
rightMost.right = cur;
cur = cur.left;
} else {
// 有左右孩子的节点第二次被经过,左子树都遍历完了,访问节点
res.add(cur.val);
rightMost.right = null;
cur = cur.right;
}
} else {
// 只有右孩子的节点只会被经过一次,直接访问
res.add(cur.val);
cur = cur.right;
}
}
} public static void inorder(TreeNode root) {
if (root == null) return;
Stack<TreeNode> stack = new Stack<>();
while (!stack.isEmpty() || root != null) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
res.add(root.val);
root = root.right;
}
} public static void inorderRecursion(TreeNode root) {
if (root == null) return;
inorderRecursion(root.left);
res.add(root.val);
inorderRecursion(root.right);
}
}

后序

/**
* 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;
* }
* }
*/
public class Solution {
static List<Integer> res; public List<Integer> postorderTraversal(TreeNode root) {
res = new ArrayList<>();
// postorderRecursion(root);
// postorder(root);
postorderMorris(root);
return res;
} public static void postorderMorris(TreeNode root) {
TreeNode cur = root;
while (cur != null) {
if (cur.left != null) {
TreeNode rightMost = cur.left;
while (rightMost.right != null && rightMost.right != cur) {
rightMost = rightMost.right;
}
if (rightMost.right == null) {
rightMost.right = cur;
cur = cur.left;
} else {
rightMost.right = null;
// 一个节点被第二次经过的时候,自底向上访问左子树的所有的右节点
visitReversedRightTree(cur.left);
cur = cur.right;
}
} else {
cur = cur.right;
}
}
// 再遍历一次
visitReversedRightTree(root);
} // 自底向上访问右节点(访问反转后的右节点)
public static void visitReversedRightTree(TreeNode root) {
// 反转右子树
TreeNode reversed = reverseRightTree(root);
TreeNode cur = reversed;
while (cur != null) {
res.add(cur.val);
cur = cur.right;
}
// 反转回去
reverseRightTree(reversed);
} // 把右子树反转
public static TreeNode reverseRightTree(TreeNode root) {
TreeNode pre = null;
TreeNode cur = root;
while (cur != null) {
TreeNode nextRight = cur.right;
cur.right = pre;
pre = cur;
cur = nextRight;
}
return pre;
} public static void postorder(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode pre = null;
while (!stack.isEmpty() || root != null) {
while (root != null) {
stack.push(root);
root = root.left;
} root = stack.pop();
if (root.right == null || root.right == pre) {
// 没有右子树或者右子树已经被访问过了
res.add(root.val);
// pre始终指向上一个被访问过的节点
pre = root;
root = null;
} else {
// 访问右子树前,先把当前节点重新入栈
stack.push(root);
root = root.right;
}
}
} public static void postorderRecursion(TreeNode root) {
if (root == null) return;
postorderRecursion(root.left);
postorderRecursion(root.right);
res.add(root.val);
}
}

二叉树遍历Java版(前中后序的递归,迭代,Morris以及两种特殊的先序遍历)的更多相关文章

  1. [C++] 非递归实现前中后序遍历二叉树

    目录 前置技能 需求描述 binarytree.h 具体实现 binarytree.cpp main.cpp 网上代码一搜一大片,大同小异咯. 书上的函数实现代码甚至更胜一筹,而且抄一遍就能用,唯一问 ...

  2. Qt实现 动态化遍历二叉树(前中后层次遍历)

    binarytree.h 头文件 #ifndef LINKEDBINARYTREE_H #define LINKEDBINARYTREE_H #include<c++/algorithm> ...

  3. 二叉树前中后/层次遍历的递归与非递归形式(c++)

    /* 二叉树前中后/层次遍历的递归与非递归形式 */ //*************** void preOrder1(BinaryTreeNode* pRoot) { if(pRoot==NULL) ...

  4. 【C++】二叉树的遍历(前中后)- 迭代法

    力扣题目:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/ 今天自己琢磨了很久如何不用递归将二叉树的遍历写出来,于是乎写出 ...

  5. 前中后序递归遍历树的体会 with Python

    前序:跟->左->右 中序:左->根->右 后序:左>右->根 采用递归遍历时,编译器/解释器负责将递归函数调用过程压入栈并保护现场,在不同位置处理根节点即可实现不 ...

  6. kmp(前中后最长相同长度)

    http://acm.hdu.edu.cn/showproblem.php?pid=4763 Theme Section Time Limit: 2000/1000 MS (Java/Others)  ...

  7. shell中调用R语言并传入参数的两种步骤

    shell中调用R语言并传入参数的两种方法 第一种: Rscript myscript.R R脚本的输出 第二种: R CMD BATCH myscript.R # Check the output ...

  8. java实现二叉树的前中后遍历(递归和非递归)

    这里使用下图的二叉树作为例子: 首先建立树这个类: public class Node { private int data; private Node leftNode; private Node ...

  9. Binary Tree Traversal 二叉树的前中后序遍历

    [抄题]:二叉树前序遍历 [思维问题]: 不会递归.三要素:下定义.拆分问题(eg root-root.left).终止条件 [一句话思路]: 节点非空时往左移,否则新取一个点 再往右移. [输入量] ...

  10. C++二叉树前中后序遍历(递归&非递归)统一代码格式

    统一下二叉树的代码格式,递归和非递归都统一格式,方便记忆管理. 三种递归格式: 前序遍历: void PreOrder(TreeNode* root, vector<int>&pa ...

随机推荐

  1. 如何解决单IP爬取网站的单IP受限问题

    由于最近博导承接了一项国家科技项目,需要对大量的网站进行爬取,但是现在的很多网站都使用了反爬手段,比如限制一个session的不同网页的访问时间间隔,甚至更有甚者直接对IP地址也做了限制.对于限制se ...

  2. 【干货】Apache DolphinScheduler2.0升级3.0版本方案

    升级背景 因项目需要使用数据质量模块功能,可以为数仓提供良好的数据质量监控功能.故要对已有2.0版本升级到3.0版本以上,此次选择测试了3.0.1 和 3.1.1 两个版本,对进行同数据等任务调度暂停 ...

  3. Binance 如何使用 Quickwit 构建 100PB 日志服务(Quickwit 博客)

    三年前,我们开源了 Quickwit,一个面向大规模数据集的分布式搜索引擎.我们的目标很宏大:创建一种全新的全文搜索引擎,其成本效率比 Elasticsearch 高十倍,配置和管理显著更简单,并且能 ...

  4. 【牛客刷题】HJ6 质数因子

    题目链接 这道题本身更多的是考察如何计算一个数的质数因子,更像是一道数学题,用到了循环的方法: package main import ( "fmt" "math&quo ...

  5. 闲鱼卖2000元的带腾讯备案的 gaapqcloud.com.cn 域名低成本获取方法!

    最近在闲鱼看到有人卖域名,声称是腾讯的备案,还卖1000多元!逆天了!这个信息差是真能割韭菜,我一查,这不就是腾讯云的全球应用加速域名吗?????这样也能赚到钱?? 获取方法 进入腾讯云全球应用加速 ...

  6. 【工程应用十一】基于PatchMatch算法的图像修复研究(inpaint)。

      这个东西是个非常古老的算法了,大概是2008年的东西,参考资料也有很多,不过基本上都是重复的.最近受一个朋友的需求,前后大概用了二十多天时间去研究,也有所成果,在这里简单的予以记录.    图像修 ...

  7. 折腾 Quickwit,Rust 编写的分布式搜索引擎-官方教程

    快速上手 在本快速入门指南中,我们将安装 Quickwit,创建一个索引,添加文档,最后执行搜索查询.本指南中使用的所有 Quickwit 命令都在 CLI 参考文档 中进行了记录. https:// ...

  8. SQLserver 数据库自定义函数

    起源 最近项目开发上使用的SQLserver数据库是2008版本,由于08版本的数据是没有字符串合并(STRING_AGG)这个函数(2017版本及以上支持)的,只有用stuff +for xml p ...

  9. C#项目—彩票选号

    C#彩票选号软件 今天做了一个彩票选号的小软件,将学到的知识点总结如下(新手小白,多提意见): 1.写程序的思路 实体类(属性.方法) No1. 随机数组集合(属性) No2. 创建集合对象(构造方法 ...

  10. Docker高级篇:实战Redis集群!从3主3从变为4主4从

    通过前面两篇,我们学会了三主三从的Redis集群搭建及主从容错切换迁移,随着业务增加,可能会有主从扩容的,所以,本文我们来实战主从扩容 PS本系列:<Docker学习系列>教程已经发布的内 ...