二叉树的迭代遍历(统一方法)

之后我们发现迭代法实现的先中后序,其实风格也不是那么统一,除了先序和后序,有关联,中序完全就是另一个风格了,一会用栈遍历,一会又用指针来遍历。

那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。如何标记呢,就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。

中序遍历

分析

二叉树的迭代遍历(统一方法) - 图1

使用null,可以看出我们将访问的节点直接加入到栈中,但如果是处理的节点则后面放入一个空节点, 这样只有空节点弹出的时候,才将下一个节点放进结果集。总体思路:使用null中节点标记是否处理,在分别进行判断。

代码

  1. class Solution {
  2. public List<Integer> inorderTraversal(TreeNode root) {
  3. /**
  4. * 统一迭代遍历(标记法)
  5. */
  6. List<Integer> list = new ArrayList<>();
  7. Stack<TreeNode> stack = new Stack<>();
  8. if (root == null) {
  9. return list;
  10. }
  11. stack.push(root);
  12. while (!stack.isEmpty()) {
  13. TreeNode node = stack.peek();
  14. if (node != null) {
  15. stack.pop();
  16. if (node.right != null) stack.push(node.right);
  17. stack.push(node);
  18. stack.push(null);
  19. if (node.left != null) stack.push(node.left);
  20. } else {
  21. stack.pop();
  22. node = stack.peek();
  23. stack.pop();
  24. list.add(node.val);
  25. }
  26. }
  27. return list;
  28. }

前序遍历

代码

  1. class Solution {
  2. public List<Integer> preorderTraversal(TreeNode root) {
  3. /**
  4. * 统一迭代遍历(标记法)
  5. */
  6. List<Integer> list = new ArrayList<>();
  7. Stack<TreeNode> stack = new Stack<>();
  8. if (root == null) {
  9. return list;
  10. }
  11. stack.push(root);
  12. while (!stack.isEmpty()) {
  13. TreeNode node = stack.peek();
  14. if (node != null) {
  15. stack.pop(); // 先将栈顶出栈,防止重复操作
  16. if (node.right != null) stack.push(node.right); // 将右左中入栈
  17. if (node.left != null) stack.push(node.left);
  18. stack.push(node);
  19. stack.push(null); // 表示遍历过该节点未访问
  20. }else {
  21. stack.pop(); // 先将空节点出栈
  22. node = stack.peek(); // 获取此时的节点
  23. stack.pop(); // 将当前节点出栈
  24. list.add(node.val); // 获取当前节点的结果
  25. }
  26. }
  27. return list;
  28. }

后序遍历

代码

  1. class Solution {
  2. public List<Integer> postorderTraversal(TreeNode root) {
  3. /**
  4. * 统一迭代遍历(标记法)
  5. */
  6. List<Integer> list = new ArrayList<>();
  7. Stack<TreeNode> stack = new Stack<>();
  8. if (root == null) {
  9. return list;
  10. }
  11. stack.push(root);
  12. while (!stack.isEmpty()) {
  13. TreeNode node = stack.peek();
  14. if (node != null) {
  15. stack.pop(); // 先将栈顶出栈,防止重复操作
  16. stack.push(node);
  17. stack.push(null); // 表示遍历过该节点未访问
  18. if (node.right != null) stack.push(node.right); // 将右左中入栈
  19. if (node.left != null) stack.push(node.left);
  20. }else {
  21. stack.pop(); // 先将空节点出栈
  22. node = stack.peek(); // 获取此时的节点
  23. stack.pop(); // 将当前节点出栈
  24. list.add(node.val); // 获取当前节点的结果
  25. }
  26. }
  27. return list;
  28. }