一、题目
要求使用非递归的方法,分别实现前、中、后序遍历二叉树。
二、分析
如果使用递归的方法,我们很简单就能实现二叉树的遍历,简单实现一个前序遍历二叉树的例子。
public void recursivePreTree(TreeNode tree) { if (tree == null) { return; } System.out.println(tree.value); recursivePreTree(tree.left); recursivePreTree(tree.right); }
那么如果不使用递归的方式,我们怎样实现二叉树的遍历呢?
我们需要在遍历的同时,把未遍历完的节点有序的保存下来,同时能够按照在完成一批节点遍历后,按照特定的顺序取出节点进行下一步遍历。而满足这种要求的数据结构就是先进后出的栈。
三、实现
1)前序
1.先将根节点入栈
2.然后访问根节点
3.如果根节点存在右节点,则将右节点入栈
4.如果根节点存在左节点,则将左节点入栈
5.重复2、3、4,直到栈为空并且所有的节点都被访问
public void recursivePreTree(TreeNode tree) { if (tree == null) { return; } TreeNode tmp = tree; Stack<TreeNode> stack = new Stack<>(); stack.push(tmp); while (!stack.empty()) { TreeNode p = stack.pop(); System.out.println(p.value); if (p.right != null) { stack.push(p.right); } if (p.left != null) { stack.push(p.left); } } }
2)中序
1.先将根节点入栈
2.将当前节点的所有左节点都入栈,直到左节点为空
3.访问栈顶节点,如果栈顶节点存在右节点,则继续第2步
4.重复第2、3步,直到栈为空并且所有的节点都被访问
public void recursiveInTree(TreeNode tree) { if (tree == null) { return; } TreeNode tmp = tree; Stack<TreeNode> stack = new Stack<>(); while (tmp != null || !stack.empty()) { while (tmp != null) { stack.push(tmp); tmp = tmp.left; } tmp = stack.pop(); System.out.println(tmp.value); if (tmp.right != null) { tmp = tmp.right; } else { tmp = null; } } }
3)后序
1.先将根节点入栈
2.将当前节点的所有左节点都入栈,直到左节点为空
3.访问栈顶节点,判断栈顶节点是否存在右节点,如果存在并且没有被访问,则将右节点入栈,否则,就访问栈顶节点
public void recursiveAfterTree(TreeNode tree) { if (tree == null) { return; } TreeNode tmp = tree; TreeNode prev = null; Stack<TreeNode> stack = new Stack<TreeNode>(); while (tmp != null || !stack.empty()) { while (tmp != null) { stack.push(tmp); tmp = tmp.left; } if (!stack.empty()) { tmp = stack.peek(); if (tmp.right == null || tmp.right == prev) { tmp = stack.pop(); System.out.println(tmp.value); prev = tmp; tmp = null; } else { tmp = tmp.right; } } } }