按之字形顺序打印二叉树

 

http://blog.csdn.net/qq_27703417/article/details/70977347

 

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推

 

第一行的时候,控制的是第二行的打印顺序,第二行的时候,控制的是第三行的打印顺序

奇数行从左到右压入栈,所以下一行按逆序打印

偶数行从右到左压入栈,所以下一行按正序打印

 

创建2个栈stack1和stack2,先将root结点压入到stack1中,然后开始循环过程:从stack1中弹出root,每次弹出一个结点时要判断它的左右子节点是否是null,如果不为null就压入到另一个栈stack2中,即这里弹出结点的栈和压入子节点的栈应该是分开的2个栈,从stack1中弹出的结点它的子节点要压入到另一个栈stack2中,当stack1中的结点弹光后,先判断stack2里面的元素是否为空,如果stack2中的结点数目也为0,那么说明在stack1弹出结点的时候没有再压入子节点到stack2中,说明此时已经没有下一层了,于是遍历结束,即遍历循环结束的判断条件是:stack1.isEmpty()并且stack2.isEmpty()。Stack1弹完后这一层就遍历结束了,它的下一层的结点都在stack2中了,为了便于循环中的操作,将stack2赋值给stack1,将stack2重新创建,这样就始终只要对stack1进行弹出,对stack2进行压入操作了,在循环代码中的实现较为简单。即基本操作过程就是从stack1中弹出结点,并将结点的子节点放入到另一个栈stack2中,当stack1遍历结束后就将stack2赋值给stack1,并将stack2重建,直到stack1和stack2都变空为止。需要注意的是:对于每一层,要求打印的顺序是不同的,对于奇数层,要求从左到右遍历结点,对于偶数层要求从右到左遍历结点,如何实现?对于偶数层,例如②③,在弹出时是先弹出③再弹出②,此时为了使得它的下一层能够从左到右输出,应该使得对于弹出的结点,先将其右孩子放入栈stack2,在将左孩子放入stack2,于是stack2中先后压入⑦⑥⑤④,弹出时的顺序就是④⑤⑥⑦;同理对于奇数层的结点,例如第三层,在遍历时的顺序是④⑤⑥⑦,它的下一层要求遍历顺序是15,14,13,12,11,⑩⑨⑧,于是在对④⑤⑥⑦的子节点压入栈是应该先压入左孩子再压入右孩子,于是先后向stack2中压入⑧⑨⑩11,12,13,14,15.总结来说,对于奇数层的结点在弹出时,它的孩子压入stack2的顺序应该是从左到右,即先压入左孩子再压入右孩子;对于偶数层的结点在弹出时,它的孩子压入stack2的顺序应该是从右到左,即先压入右孩子再压入左孩子。这种交替需要在循环体中写2中遍历子孩子的代码,并且记录一个层数计数器levelCount,通对其的奇偶性判断来决定使用哪一段代码即可。

 

import java.util.*;  
//之字形遍历:使用2个栈,遍历先压入左结点再压入右结点和先右结点再左结点交替进行;自动换行,不用last和nlast  
public class Solution {  
    //创建结果集,成员变量  
    ArrayList<ArrayList<Integer>> results;  
    public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {  
        results=new ArrayList<ArrayList<Integer>>();  
        //特殊输入  
        if(pRoot==null) return results;  
        //调用方法解决问题  
        this.process(pRoot);  
        //返回结果集  
        return results;  
    }  
      
    //该方法用来之字形遍历二叉树,并将每层结果放入到results中  
    private void process(TreeNode root){  
        //①创建辅助栈  
        Stack<TreeNode> stack1=new Stack<>();  
        Stack<TreeNode> stack2=new Stack<>();  
        //每一层的结果集  
        ArrayList<Integer> list=new ArrayList<>();  
        //第一变量记录层数  
        int levelCount=1;  
        //②先将root压入栈  
        stack1.push(root);  
        //③循环:弹栈遍历--左右孩子入栈--交换stack1和stack2  
        //只要stack1和stack2不全为空就可以继续  
        while(!(stack1.isEmpty()&&stack2.isEmpty())){  
            //弹出并遍历  
            TreeNode temp=stack1.pop();  
            list.add(temp.val);  
            //左右孩子压入stack2中  
            if(levelCount%2!=0){  
                //奇数层,先左再右  
                if(temp.left!=null){  
                    stack2.push(temp.left);  
                }  
                if(temp.right!=null){  
                    stack2.push(temp.right);  
                }  
            }else{  
                //偶数层,先右再左  
                if(temp.right!=null){  
                    stack2.push(temp.right);  
                }  
                if(temp.left!=null){  
                    stack2.push(temp.left);  
                }  
            }  
              
            //判断此时stack1是否为空,即本层是否遍历完成  
            if(stack1.isEmpty()){  
                //本层遍历完成:换list,换stack1和stack2;层数加1  
                results.add(list);  
                list=new ArrayList<Integer>();  
                stack1=stack2;  
                stack2=new Stack<TreeNode>();  
                //千万记得层数+1  
                levelCount++;  
            }  
        }  
    }  
}  



public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer> > list = new ArrayList<ArrayList<Integer>>();
        if(pRoot == null)
            return list;
        
        Print(pRoot,list);
        
        return list;
    }
    
    public void Print(TreeNode root,ArrayList<ArrayList<Integer> > list) {
        Stack<TreeNode> s1 = new Stack<TreeNode>();
        Stack<TreeNode> s2 = new Stack<TreeNode>();
        
        s1.push(root);
        int level =1;
        ArrayList<Integer> temp = new ArrayList<Integer>();
        
        while(!s1.isEmpty()){
                if(level%2>0){   //单数行 先左后右
                    
                    while(!s1.isEmpty()){   //s1中的数全部放到list,并把左右孩子放到s2
                        TreeNode node = s1.pop();
                        temp.add(node.val);
                        if(node.left!=null)
                            s2.push(node.left);
                        
                        if(node.right!=null)
                            s2.push(node.right);
                    }
                        
                }else if(level%2==0){
                    while(!s1.isEmpty()){ 
                        TreeNode node = s1.pop();
                        temp.add(node.val);
                        if(node.right!=null)
                            s2.push(node.right);
                        
                        if(node.left!=null)
                            s2.push(node.left);
                        
                    }
                }
                
                s1 = s2;
                s2 = new Stack<TreeNode>();
                list.add(temp);
                temp = new ArrayList<Integer>();
                level++;
            
        }
    }

 

 

 

posted on 2017-08-21 23:28  zhangxiaoyu  阅读(198)  评论(0)    收藏  举报

导航