二叉树的遍历

先序

/**
* 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. gym.ObservationWrapper使用时的注意点——reset和step函数可以覆盖observation函数

    记录一个刚学习到的gym使用的点,就是gym.ObservationWrapper使用时的注意点--reset和step函数可以覆盖observation函数. 给出代码: import gym cl ...

  2. springboot实现事务管理

    Springboot实现事务步骤1.在启动类加上@EnableTransactionManagement 2.在业务层方法上加 @Transactional(rollbackFor = Excepti ...

  3. 你要的高效方案!基于Apache SeaTunnel快速集成SAP进入Redshift

    摘要 本文深入探讨了Apache SeaTunnel及其商业版可视化数据同步平台WhaleTunnel在数据整合领域的应用,特别是如何高效地将SAP系统中的数据同步到Amazon Redshift.通 ...

  4. Edge实验性功能中文翻译

    平行下载 启用平行下载以加速下载速度.- Mac, Windows, Linux, Android #enable-parallel-downloading 已启用 临时恢复 M125 标记 临时恢复 ...

  5. MySQL8服务无法启动,服务没有报告任何错误

    MySQL8服务无法启动,服务没有报告任何错误 错误信息: 免安装版mysql-8.0.15-winx64.zip 按照教程来安装,解压,增加my.ini文件,修改文件内部的地址信息,配置环境变量pa ...

  6. 9组-Beta冲刺-4/5

    一.基本情况(15分) 队名:不行就摆了吧 组长博客:9组-Beta冲刺-4/5 GitHub链接:https://github.com/miaohengming/studynote/tree/mai ...

  7. ibatis执行存储过程,java.lang.ArrayIndexOutOfBoundsException: 0

    在项目开发中遇到一个问题,ibatis执行存储过程时报错 <procedure id="insertStatisticsResult_settle" parameterCla ...

  8. 使用 refreshNuxtData 刷新 Nuxt应用 中的数据

    title: 使用 refreshNuxtData 刷新 Nuxt应用 中的数据 date: 2024/8/21 updated: 2024/8/21 author: cmdragon excerpt ...

  9. harbor重启后无法自启动解决方案

    1. 创建 systemd 服务单元文件 编辑服务文件: 使用以下命令创建并编辑 systemd 服务文件: sudo vim /etc/systemd/system/harbor.service 添 ...

  10. redux开发中的一个小坑

    redux的actiontypes,不可以重名,重名将会报错 When called with an action of type "inserttoken", the slice ...