二叉树遍历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); } }
本文作者:n1ce2cv
本文链接:https://www.cnblogs.com/sprinining/p/16356686.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步