之前讲了递归调用二叉树,下面简单的介绍非递归二叉树遍历。
非递归二叉树遍历是采用的栈的方式,将结点分为,根节点,左子树,右子树的顺序分别在不同的时候入栈和出栈。
1:非递归前序遍历(DLR)
1 /* 2 * 非递归二叉树遍历方法 3 */ 4 public class BinTreeNoRecur { 5 6 //非递归的方法实现和前序遍历(DLR)一样的效果,思想是先将一个结点入栈,如果不为空,则直接输出给节点,并且将输出的结点作为当前节点 7 //然后再将右子树入栈,左子树入栈,右子树是后出来,所以先进栈 8 public static void preOrderNoRecur(BinTreeNode root){ 9 BinTreeNode curr; 10 LinStack ls=new LinStack(); 11 if (ls==null) return; 12 ls.push(root); //首先将栈顶的元素注入栈中 13 while(ls.notEmpty()){ //当栈不为空的时候开始遍历 14 curr=(BinTreeNode) ls.pop(); //出栈得到栈顶的元素 15 System.out.print(" "+curr.getData()); 16 17 if (curr.getRightChild()!=null) //如果右孩子节点不为空,则将右孩子结点压入栈中 18 ls.push(curr.getRightChild()); 19 if(curr.getLeftChild()!=null) 20 ls.push(curr.getLeftChild()); //如果左孩子节点不为空,则将左孩子结点压入栈中 21 } 22 } 23
2:非递归二叉树中序遍历
//非递归实现中序遍历 思考一下这个方法为什么错误了? public static void inOrderNoRecur(BinTreeNode root){ LinStack lins=new LinStack(); if (root==null) return; BinTreeNode curr=root; lins.push(curr); //直接将根部元素压入栈底 while(lins.notEmpty()){ //判断栈是否为空 //这里面是while循环,而不是if是因为需要将所有的左子树的结点都遍历完,再遍历右子树 while (curr.getLeftChild()!=null) { lins.push(curr.getLeftChild()); curr=curr.getLeftChild(); } curr=(BinTreeNode) lins.pop(); System.out.print(" "+curr.getData()); if (curr.getRightChild()!=null) { curr=curr.getRightChild(); lins.push(curr); } } }
正确方法:
1 //非递归实现中序遍历 2 public static void inOrderNoRecur(BinTreeNode root){ 3 4 LinStack lins=new LinStack(); 5 if (root==null) return; 6 BinTreeNode curr=root; 7 //判断栈是否为空或者判断堆栈是否为空 8 while(curr!=null||lins.notEmpty()){ 9 //这里面是while循环,而不是if是因为需要将所有的左子树的结点都遍历完,再遍历右子树 10 while (curr!=null) { 11 //第一次不为空的时候压入的是根结点,之后一直遍历左子树 12 lins.push(curr); 13 curr=curr.getLeftChild(); 14 } 15 curr=(BinTreeNode) lins.pop(); 16 System.out.print(" "+curr.getData()); 17 curr=curr.getRightChild(); 18 } 19 }
3:后序二叉树的非递归遍历
1 while(curr!=null||linstack.notEmpty()){ 2 //先进入左子树中 3 while(curr!=null){ 4 linstack.push(curr); 5 curr=curr.getLeftChild(); 6 } 7 //获得栈顶的位置,因为在上面的while循环中,先push进去一个结点,在传入下一个结点中 8 //如此,最后的一个结点一定会没有左子树,那么此时curr指向的是一个空节点。 9 //因此我们得将当前节点指定为栈的顶节点 10 curr=(BinTreeNode) linstack.getTop(); 11 12 /*如果右结点为空,或者右结点之前遍历过,表明对于一个子树,其左结点已经打印完毕,打印根结点*/ 13 if(curr.getRightChild()==null||curr.getRightChild()==preNode){ 14 curr=(BinTreeNode) linstack.pop(); 15 System.out.print(" "+curr.getData()); 16 preNode = curr; 17 curr=null; 18 } 19 else{ 20 curr=curr.getRightChild(); 21 } 22 }