一、绪论
上一章中,我们粗略的复习了二叉树的遍历,不过是采用递归的方式遍历的。扩展来说,二叉树的遍历是可以推广到任何树结构的。但是,这里要强调一下,任何递归方法可以解决的问题都能用非递归的方法去实现。因为递归的思想是利用函数栈来保存信息,我们可以使用自己写的数据结构来代替函数栈,所以也可以实现相同的目的。
二、目的
采用非递归的方式实现对二叉树的遍历。
2.1、先序遍历
拿先序遍历为例,介绍思想如下:
1、申请新的栈,记作stack。将头节点root压入栈中;
2、从栈中弹出栈顶节点,记作cur,打印cur的value,再将cur的右子节点(if !=null)压入栈中,最后将cur的左子节点(if !=null)压入栈中;
3、重复2,直到stack为空,过程结束。
1 public void preOrderUnRecur(Node head){ 2 if(head != null){ 3 Stack<Node> stack = new Stack<Node> () ; 4 stack.add(head) ; 5 6 while(stack!=null){ 7 head = stack.pop() ; 8 System.out.println(head.value+" ") ; 9 if(head.right!=null){ 10 stack.push(head.right) ; 11 } 12 13 if(head.left!=null){ 14 stack.push(head.left) ; 15 } 16 } 17 } 18 }
2.2、中序遍历
其实本质上来说,先序和中序的差异不大,他的目的先是将左子树压入栈中,再取出来,弹出来的时候仍要判断右子树是否为空。
1、申请新的栈stack,将根节点root压入栈中 ;
2、如果栈和节点root不为空,则将root.left压入栈中,直到root.left==null ;
3、弹出栈的元素,如果弹出来的节点有右子节点,则将右子节点加入栈中,进入2中循环 ;
4、循环到stack.isEmpty() && root == null ;
1 public void inOrderUnRecur( Node head ){ 2 if(head!=null){ 3 Stack<Node> stack = new Stack<Node>() ; 4 5 while(!(stack.isEmpty() && head == null)){ 6 if(head!=null){ 7 stack.push(head) ; 8 head = head.left ; 9 }else{ 10 head=stack.pop() ; 11 System.out.println(head.value + " ") ; 12 head = head.right ; 13 } 14 } 15 16 } 17 }
2.3、后序遍历
后序遍历会稍微复杂一点,按照步骤来说,有如下操作:
1、建立新栈,将头节点压入栈中;
2、如果栈不为空会一直循环,在循环体内,另一个index来记录栈顶元素;
3、判断,如果,栈顶元素index的左子节点不为空,并且不等于根节点的左子节点和右子节点,证明这个index的左边还没有遍历过,将index.left压入栈中;
4、判断,如果,栈顶元素index的右子节点不为空,并且不等于根节点的右子节点,证明这恶index的右边没有遍历过,将index.right压入栈中;
5、否则,将输出根节点,并且令栈顶元素 = 根节点 。
1 public void posOrderUnRecur01(Node head){ 2 if(head != null) { 3 Node index = null; 4 Stack<Node> stack = new Stack<Node>() ; 5 stack.push(head) ; 6 7 8 while (!stack.isEmpty()){ 9 index = stack.peek() ; 10 if(index.left!=null && head!=index.left && head!=index.right){ 11 stack.push(index.left) ; 12 }else if(index.right!=null && head!=index.right){ 13 stack.push(index.right) ; 14 }else { 15 System.out.print(stack.pop().value+" ") ; 16 head = index ; 17 } 18 } 19 20 } 21 }