1. 对于树的遍历我们最常用的三种遍历方法分别是前序遍历、中序遍历和后序遍历,使用的方法是深度优先遍历树的每一个节点,这些遍历方法都是使用递归函数来进行实现的,在数据量大的情况下是比较低效的,原因在于系统帮助我们调用了一个栈并且做了诸如保护现场和恢复现场等复杂的操作,才使得遍历可以使用非常简单的代码来实现,所以我们可以模仿系统中调用的栈自己可以来写一下栈,模仿其中的过程就可以完成对于三种遍历算法的实现,使用自定义的栈来代替系统栈可以得到效率上的提升,下面是对于先序遍历的非递归算法的实现
2. 首先模仿这个系统栈我们需要清楚的是系统栈为我们做了什么事情,下面以一棵二叉树为例来模仿其中的节点入栈与出栈的过程
创建的二叉树如下:
先序遍历为:1 2 5 3 4
下面是模仿元素进栈与出栈的过程:
① 一开始的时候栈为空那么1节点进栈,而且左右孩子节点不为空那么将左右节点压入到栈中,需要注意的是先序遍历是先遍历2节点然后再遍历4节点而弹出栈顶元素的时候是先进后出所以需要先加入1节点的右节点然后再加入左节点
② 弹出2节点发现2节点的左右节点都存在那么先将2节点的右节点压入栈顶,左节点压入到栈顶
③ 弹出5节点发现左右孩子都为空那么不进行任何的操作
④ 弹出3节点发现左右孩子都为空不进行任何操作
⑤ 弹出4节点发现左右孩子都为空不进行任何操作
这个时候栈为空栈那么结束整个while循环
3. 具体的代码如下:
import java.util.Stack;
public class Main {
public static void main(String[] args) {
TreeNode<Integer> root = new TreeNode<Integer>(1);
TreeNode<Integer> l = new TreeNode<Integer>(2);
TreeNode<Integer> r = new TreeNode<Integer>(4);
TreeNode<Integer> ll = new TreeNode<Integer>(5);
TreeNode<Integer> lr = new TreeNode<Integer>(3);
root.left = l;
root.right = r;
l.left = ll;
l.right = lr;
preOrder(root);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static void preOrder(TreeNode<Integer> root) {
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode<Integer> node = stack.pop();
System.out.print(node.val + " ");
//把当前节点的左右孩子加进来
//注意应该先是将右孩子加进来
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}
}
public static class TreeNode<T>{
T val;
TreeNode<T> left;
TreeNode <T> right;
public TreeNode(T val) {
super();
this.val = val;
}
}
}