二叉树的迭代遍历(统一方法)
之后我们发现迭代法实现的先中后序,其实风格也不是那么统一,除了先序和后序,有关联,中序完全就是另一个风格了,一会用栈遍历,一会又用指针来遍历。
那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。如何标记呢,就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。
中序遍历
分析

使用null,可以看出我们将访问的节点直接加入到栈中,但如果是处理的节点则后面放入一个空节点, 这样只有空节点弹出的时候,才将下一个节点放进结果集。总体思路:使用null中节点标记是否处理,在分别进行判断。
代码
class Solution {public List<Integer> inorderTraversal(TreeNode root) {/*** 统一迭代遍历(标记法)*/List<Integer> list = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();if (root == null) {return list;}stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.peek();if (node != null) {stack.pop();if (node.right != null) stack.push(node.right);stack.push(node);stack.push(null);if (node.left != null) stack.push(node.left);} else {stack.pop();node = stack.peek();stack.pop();list.add(node.val);}}return list;}
前序遍历
代码
class Solution {public List<Integer> preorderTraversal(TreeNode root) {/*** 统一迭代遍历(标记法)*/List<Integer> list = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();if (root == null) {return list;}stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.peek();if (node != null) {stack.pop(); // 先将栈顶出栈,防止重复操作if (node.right != null) stack.push(node.right); // 将右左中入栈if (node.left != null) stack.push(node.left);stack.push(node);stack.push(null); // 表示遍历过该节点未访问}else {stack.pop(); // 先将空节点出栈node = stack.peek(); // 获取此时的节点stack.pop(); // 将当前节点出栈list.add(node.val); // 获取当前节点的结果}}return list;}
后序遍历
代码
class Solution {public List<Integer> postorderTraversal(TreeNode root) {/*** 统一迭代遍历(标记法)*/List<Integer> list = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();if (root == null) {return list;}stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.peek();if (node != null) {stack.pop(); // 先将栈顶出栈,防止重复操作stack.push(node);stack.push(null); // 表示遍历过该节点未访问if (node.right != null) stack.push(node.right); // 将右左中入栈if (node.left != null) stack.push(node.left);}else {stack.pop(); // 先将空节点出栈node = stack.peek(); // 获取此时的节点stack.pop(); // 将当前节点出栈list.add(node.val); // 获取当前节点的结果}}return list;}
