非递归遍历就是迭代遍历
模拟的就是递归中的过程,代码比递归略微复杂
//非递归前序遍历
public static void prOrderNoR(TreeNode root){
Stack<TreeNode> st = new Stack<>();
TreeNode curNode = root;
while(curNode != null || !st.isEmpty()){
//走到空时结束
while(curNode != null){
//首先访问根
System.out.print(curNode.value + " ");
//访问根的左子树
st.push(curNode);
curNode = curNode.left;
}
//获取栈顶元素
curNode = st.pop();
//访问栈顶元素的右子树
curNode = curNode.right;
}
System.out.println();
}
根左右的顺序,进行压栈
public static void inOrderNoR(TreeNode root){
Stack<TreeNode> st = new Stack<>();
TreeNode curNode = root;
// curNode != null: 表示已curNode为根的子树需要访问
// !st.isEmpty(): 之前压栈的子树没有访问完
while(curNode != null || ! st.isEmpty()){
while(curNode != null){
//访问左子树
st.push(curNode);
curNode = curNode.left;
}
//访问根
curNode = st.pop();
System.out.print(curNode.value + " ");
//访问右子树
curNode = curNode.right;
}
System.out.println();
}
左根右进行压栈,与前序基本相同
重点是后序遍历,需要一个前驱节点进行标记
public static void postOrderNoR(TreeNode root){
Stack<TreeNode> st = new Stack<>();
TreeNode curNode = root;
TreeNode prev = null;
while(curNode != null || ! st.isEmpty()){
while(curNode != null){
//左子树
st.push(curNode);
curNode = curNode.left;
}
//根: 访问完右子树之后,才能访问根
//curNode = st.pop(); 有可能导致元素访问不到
curNode = st.peek();
//判断右子树是由已经访问完:
// 1. curNode.right == null : 没有右子树
// 2. curNode.right == prev: 有右子树,并且右子树的根上一次已经访问结束,即右子树访问完成
if(curNode.right == null || curNode.right == prev){
System.out.print(curNode.value + " ");
prev = curNode;
st.pop();
curNode = null;
}
else{
//右子树
curNode = curNode.right;
}
}
System.out.println();
}
而且左子树遍历完后不能直接进行右边,因为要判断右边是否是空,也要判断右边是否是上次遍历过了,如果遍历过了就直接输出根了