目录
- 前序遍历
- 中序遍历
- 后序遍历
前序遍历
递归遍历
public List<Integer> preorderTraversal(TreeNode root) { List<Integer> ans = new ArrayList<>(); traversal(ans, root); return ans; } private void traversal(List<Integer> ans, TreeNode root) { // 递归的结束条件。 if (null == root) { return; } ans.add(root.val); // 遍历左子树。 traversal(ans, root.left); // 遍历右子树 traversal(ans, root.right); }
迭代遍历
第一种方式
public List<Integer> preorderTraversal(TreeNode root) { // 存放最终的结果。 List<Integer> ans = new LinkedList<>(); // 前序遍历使用的栈。 Deque<TreeNode> stack = new LinkedList<>(); while (!stack.isEmpty() || null != root) { // 加入左节点. while (null != root) { stack.push(root); // 因为是前序遍历将节点的值加入ans中。 ans.add(root.val); root = root.left; } // 遍历右子树。 root = stack.pop().right; } return ans; }
第二种方式
public List<Integer> preorderTraversal(TreeNode root) { // 存储节点值的集合。 List<Integer> ans = new LinkedList<>(); // 二叉树为空,直接返回集合。 if (null == root) { return ans; } // 遍历二叉树使用的栈。 Deque<TreeNode> stack = new LinkedList<>(); stack.push(root); // 前序遍历 while (!stack.isEmpty()) { TreeNode node = stack.pop(); if (null != node) { // 压入右节点。 if (null != node.right) { stack.push(node.right); } // 压入左节点。 if (null != node.left) { stack.push(node.left); } // 压入根节点。 stack.push(node); // 压入一个null值,作为分隔符。 stack.push(null); } else { // 当node=null的时候,将节点的值加入集合当中。 ans.add(stack.pop().val); } } return ans; }
Mirrors遍历
public List<Integer> preorderTraversal(TreeNode root) { // 存储最终答案的集合。 List<Integer> ans = new LinkedList<>(); // Mirrors遍历使用的指针。 TreeNode p1 = root, p2 = null; // Mirrors遍历 while (null != p1) { p2 = p1.left; if (null == p2) { // 左子树为空,将结果加入集合,指针直接向右子树移动。 ans.add(p1.val); } else { // 左子树不为空,找到左子树的最右节点,判断该节点的右节点。 // 寻找最有节点。 while (null != p2.right && p1 != p2.right) { p2 = p2.right; } // 如果最右节点的右节点是空。 if (null == p2.right) { // 进行连接,将最右节点的右节点设置为当前节点。 p2.right = p1; // 节点加入集合。 ans.add(p1.val); // 当前节点往左移动。 p1 = p1.left; continue; } else { // 最右节点的右节点不是null,指针向有移动,断开连接。 p2.right = null; } } p1 = p1.right; } return ans; }
中序遍历
递归遍历
public List<Integer> inorderTraversal(TreeNode root) { // 存放节点的值。 List<Integer> ans = new LinkedList<>(); traversal(ans, root); return ans; } private void traversal(List<Integer> ans, TreeNode root) { // 递归结束条件。 if (null == root) { return; } // 遍历左子树。 traversal(ans, root.left); // 加入节点的值。 ans.add(root.val); // 遍历右子树。 traversal(ans, root.right); }
迭代遍历
第一种方式
public List<Integer> inorderTraversal(TreeNode root) { // 存放结果的集合。 List<Integer> ans = new LinkedList<>(); // 遍历使用的栈 Deque<TreeNode> stack = new LinkedList<>(); // 中序遍历 while (!stack.isEmpty() || null != root) { // 加入左节点。 while (null != root) { stack.push(root); root = root.left; } // 加入节点。 root = stack.pop(); // 将当前节点加入集合。 ans.add(root.val); // 遍历右子树。 root = root.right; } return ans; }
第二种方式
public List<Integer> inorderTraversal(TreeNode root) { // 存放结果的集合。 List<Integer> ans = new LinkedList<>(); // 二叉树为空。 if (null == root) { return ans; } // 遍历二叉树使用的栈。 Deque<TreeNode> stack = new LinkedList<>(); stack.push(root); // 中序遍历。 while (!stack.isEmpty()) { TreeNode node = stack.pop(); if (null != node) { // 压入右节点。 if (null != node.right) { stack.push(node.right); } // 压入当前节点。 stack.push(node); // 压入null值作为分隔符。 stack.push(null); // 压入左节点。 if (null != node.left) { stack.push(node.left); } } else { // 将节点加入集合。 ans.add(stack.pop().val); } } return ans; }
Mirrors遍历
public List<Integer> inorderTraversal(TreeNode root) { // 存储答案的集合. List<Integer> ans = new LinkedList<>(); // Mirrors遍历需要的指针 TreeNode p1 = root, p2 = null; // Mirrors遍历 while (null != p1) { p2 = p1.left; if (null == p2) { // 左子树为空。 // 将节点加入集合。 ans.add(p1.val); } else { // 左子树不为空,寻找中序前驱节点。 while (null != p2.right && p1 != p2.right) { p2 = p2.right; } if (null == p2.right) { // 前驱节点的右节点为空,将当前节点设置为前驱节点的右节点。 p2.right = p1; // 节点向左移动。 p1 = p1.left; continue; } else { // 前驱节点的右节点不为空,说明左子树已经遍历完成。 // 将当前节点加入集合。 ans.add(p1.val); // 将前驱节点的右子树设置为null。 p2.right = null; } } p1 = p1.right; } return ans; }
后序遍历
递归遍历
public List<Integer> postorderTraversal(TreeNode root) { // 存储结果的集合。 List<Integer> ans = new LinkedList<>(); traversal(ans, root); return ans; } private void traversal(List<Integer> ans, TreeNode root) { // 递归的结束条件。 if (null == root) { return; } // 遍历左子树 traversal(ans, root.left); // 遍历右子树 traversal(ans, root.right); // 遍历根节点。 ans.add(root.val); }
迭代遍历
第一种方式
public List<Integer> postorderTraversal(TreeNode root) { // 存储结果的集合。 List<Integer> ans = new LinkedList<>(); // 遍历需要的栈。 Deque<TreeNode> stack = new LinkedList<>(); // 进行后序遍历。 while (!stack.isEmpty() || null != root) { while (null != root) { stack.push(root); root = root.left; } root = stack.peek(); if (null != root) { // 当前已经遍历完了左子树。 // 压入一个null作为标记。 stack.push(null); // 不为空。 root = root.right; } else { // 为空,代表当前节点右子树已经遍历完成。 stack.pop(); ans.add(stack.pop().val); root = null; } } return ans; }
第二种方式
public List<Integer> postorderTraversal(TreeNode root) { // 存储结果的集合。 List<Integer> ans = new LinkedList<>(); // 二叉树为空。 if (null == root) { return ans; } // 遍历二叉树使用的栈。 Deque<TreeNode> stack = new LinkedList<>(); stack.push(root); // 进行后序遍历。 while (!stack.isEmpty()) { TreeNode node = stack.pop(); if (null != node) { // 压入根节点。 stack.push(node); // 压入null作为当前节点已经访问过了。 stack.push(null); // 压入右节点。 if (null != node.right) { stack.push(node.right); } // 压入左节点。 if (null != node.left) { stack.push(node.left); } } else { // 如果为空,说明当前节点已经遍历完成。 ans.add(stack.pop().val); } } return ans; }
Mirrors遍历
public List<Integer> postorderTraversal(TreeNode root) { // 存储结果的集合。 List<Integer> ans = new LinkedList<>(); // 为了遍历,常见一个虚拟节点。 TreeNode dummy = new TreeNode(0, root, null); // Mirrors遍历需要的指针。 TreeNode p1 = dummy, p2 = null; // 进行Mirrors遍历。 while (null != p1) { p2 = p1.left; // 当前节点的左子树为空的时候,直接向右子树移动。 if (null != p2) { // 当前节点的左子树不为空。 // 寻找前驱节点。 while (null != p2.right && p1 != p2.right) { p2 = p2.right; } if (null == p2.right) { // 前驱节点的右子树为空,进行连接。 p2.right = p1; // 指针向左移动。 p1 = p1.left; continue; } else { // 前驱节点的右子树不为空,说明当前节点的已经访问完成了。 // 断开连接。 p2.right = null; // 将从p1的左节点一直到前驱节点全部加入到集合当中。 addNode(ans, p1.left); } } p1 = p1.right; } // 销毁哑节点。 dummy.left = null; return ans; } private void addNode(List<Integer> ans, TreeNode root) { // 获取集合当中已有元素的个数。 int size = ans.size(); // 倒序插入节点。 while (null != root) { ans.add(size, root.val); root = root.right; } }
note:后序遍历的Mirrors遍历,如果不使用容器,需要反转右子树。这样作者没有想到更完善的方法,如果有更好的方法,欢迎告诉作者。
作者目前只是一个自学编程的小白, 如果您发现文章又任何错误的地方,欢迎指出。
原创文章,作者:端木书台,如若转载,请注明出处:https://blog.ytso.com/269494.html