二叉树的遍历

先序

/**
* 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. mini_imagenet 数据集生成工具 (续)

    续接前文:  mini_imagenet 数据集生成工具 ============================================ 前文接受了mini_imagenet数据集的生成,但 ...

  2. Ubuntu22.04下安装chrome浏览器

    Ubuntu下Chrome的下载: 地址: https://www.google.cn/intl/zh-CN/chrome/ 下载后的文件: 安装: 命令: sudo dpkg -i google-c ...

  3. C# 命名空间和程序集 小记

    前言 本文只是为了复习,巩固,和方便查阅,一些知识点的详细知识会通过相关链接和文献标记出来. 命名空间 1.1 概念 可以把命名空间看做字符串,他加在类名或类型名前面并且通过点进行分割 既然看做是字符 ...

  4. 破局SAP实施难题、降低开发难度,定制化需求怎样快速上线?

    前言 SAP 是全球领先的业务流程管理软件供应商之一,其提供广泛的模块化解决方案和套件,所开发的软件解决方案面向各种规模的企业,帮助客户规划和设计业务流程.分析并高效设计整个价值链,以更好的了解和响应 ...

  5. [POI2008] POC-Trains 题解

    前言 题目链接:洛谷. 时间复杂度和输入同阶的做法. 题意简述 有 \(n\)(\(n \leq 10^3\))个长 \(m\) 的字符串,\(q\)(\(q \leq 10^5\))次操作,交换两个 ...

  6. .NET周刊【8月第1期 2024-08-04】

    国内文章 EF Core性能优化技巧 https://www.cnblogs.com/baibaomen-org/p/18338447 这篇文章介绍了在代码层面上优化EF Core实例池和拆分查询的方 ...

  7. 基于MonoGame重制《俄罗斯方块》游戏

    两年前,我使用C#基于MonoGame编写了一款<俄罗斯方块>游戏,相关介绍可以参考[这篇文章].最近,使用业余时间将之前的基于MonoGame的游戏开发框架重构了一下,于是,也就趁此机会 ...

  8. dubbo序列化问题(二)hession2与kryo切换 转

    dubbo提供了好几种序列化方式,一般我们都是用的是默认的hession2,而dubbox为我们增加了kryo和fst许了方式,主要体现在速度快,占用内存小,然后我们将序列化配置改为是用kryo: & ...

  9. AOP(代理模式)

    利用特性Attribute+反射+代理类实现AOP 一.定义自定义特性 /// <summary> /// 自定义特性,方法执行前调用 /// </summary> publi ...

  10. SQL中解决i+1 & values中插入变量

    基于JDBC环境下使用mysql插入数据的一些小问题 下方代码用于实现 批量向数据库中插入数据 一般为"垃圾"数据 代码例子实现i+1的效果 i=1 i+1=2 for (int ...