二叉树遍历Java版(前中后序的递归,迭代,Morris以及两种特殊的先序遍历)
二叉树的遍历
先序
/**
* 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以及两种特殊的先序遍历)的更多相关文章
- [C++] 非递归实现前中后序遍历二叉树
目录 前置技能 需求描述 binarytree.h 具体实现 binarytree.cpp main.cpp 网上代码一搜一大片,大同小异咯. 书上的函数实现代码甚至更胜一筹,而且抄一遍就能用,唯一问 ...
- Qt实现 动态化遍历二叉树(前中后层次遍历)
binarytree.h 头文件 #ifndef LINKEDBINARYTREE_H #define LINKEDBINARYTREE_H #include<c++/algorithm> ...
- 二叉树前中后/层次遍历的递归与非递归形式(c++)
/* 二叉树前中后/层次遍历的递归与非递归形式 */ //*************** void preOrder1(BinaryTreeNode* pRoot) { if(pRoot==NULL) ...
- 【C++】二叉树的遍历(前中后)- 迭代法
力扣题目:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/ 今天自己琢磨了很久如何不用递归将二叉树的遍历写出来,于是乎写出 ...
- 前中后序递归遍历树的体会 with Python
前序:跟->左->右 中序:左->根->右 后序:左>右->根 采用递归遍历时,编译器/解释器负责将递归函数调用过程压入栈并保护现场,在不同位置处理根节点即可实现不 ...
- kmp(前中后最长相同长度)
http://acm.hdu.edu.cn/showproblem.php?pid=4763 Theme Section Time Limit: 2000/1000 MS (Java/Others) ...
- shell中调用R语言并传入参数的两种步骤
shell中调用R语言并传入参数的两种方法 第一种: Rscript myscript.R R脚本的输出 第二种: R CMD BATCH myscript.R # Check the output ...
- java实现二叉树的前中后遍历(递归和非递归)
这里使用下图的二叉树作为例子: 首先建立树这个类: public class Node { private int data; private Node leftNode; private Node ...
- Binary Tree Traversal 二叉树的前中后序遍历
[抄题]:二叉树前序遍历 [思维问题]: 不会递归.三要素:下定义.拆分问题(eg root-root.left).终止条件 [一句话思路]: 节点非空时往左移,否则新取一个点 再往右移. [输入量] ...
- C++二叉树前中后序遍历(递归&非递归)统一代码格式
统一下二叉树的代码格式,递归和非递归都统一格式,方便记忆管理. 三种递归格式: 前序遍历: void PreOrder(TreeNode* root, vector<int>&pa ...
随机推荐
- vue项目之菜单管理项目实现
1.背景 2.菜单导航实现 代码: <template> <el-breadcrumb separator-class="el-icon-arrow-right" ...
- centos 安装 图像识别工具 tesseract-ocr 流程
(1)首先安装依赖的leptonica库:wget http://www.leptonica.com/source/leptonica-1.72.tar.gztar -xvf leptonica-1. ...
- 《重学Java设计模式》笔记——建造者模式
1. 建造者模式可以解决什么问题 我家里有各种形状的瓷器,盘子或者碗.虽然形状不同,但是所用的材料基本上是一样的,比如土.水.釉.彩这些基本的东西. 但是做不同款式的瓷器,方法是不同的.假如说我现在已 ...
- 11. 基于ARM Cortex-A9中断详解
一.中断概念 操作系统中,中断是很重要的组成部分.出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行. 有了中断系统才可以不用一直 ...
- CASIO fx-991CN X 使用
复数转换 \(a+b \, {\mathrm i} \leftrightarrow r \angle \theta\) 进入复数运算模式 菜单 2 输入待转换数 OPTN ▼,选择目标格式. = 可通 ...
- 分布式缓存应用场景与redis持久化机制
redis 参考目录: 生产级Redis 高并发分布式锁实战1:高并发分布式锁如何实现 https://www.cnblogs.com/yizhiamumu/p/16556153.html 生产级Re ...
- Splay/LCT 学习笔记
唔,其实我不会 Splay,但是我会 LCT. 众所周知,会 LCT 和会 Splay 是两回事,因为 LCT 只需要旋至根即可. 到现在还是不会,但是先把 LCT 的 Splay 写一下吧. 自己复 ...
- 2023/11/16 NOIP 模拟赛
T1 基于1的算术 标签 暴力枚举 思路1 赛时想了个假的 DP,只拿了 77 分,,, 小于 \(10^{15}\) 的仅由 \(1\) 组成的数只有 \(15\) 个,直接枚举即可. 想了一个做法 ...
- Angular Material 18+ 高级教程 – Datepicker の Calendar & Custom DateAdapter (Temporal)
前言 本篇只会教 Angular Material Datepicker 里最关键的组件 -- Calendar 组件. 还有如何自定义 DateAdapter,让 Calendar 支持 TC39 ...
- Asp.net core 学习笔记之 authentication + authorization + identity + identity server 4 + angular 第六篇 (authorization 之 simple authorization, role based, claim based, policy based)
authorization 授权是什么 ? 就是某个人必须符合某些条件才能做某些事儿 某个人指的是登入的 user 某些条件指的是 policy requirements 事儿指的是访问 contro ...