数据结构与算法分析笔记与总结(java实现)--二叉树17:按之字形顺序打印二叉树

来源:互联网 发布:淘宝店进货渠道 编辑:程序博客网 时间:2024/05/22 13:09

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

  

思路:方法一,思路很简单但是毫无技巧性可言。还是按照按层遍历的方式设置一个队列queue,分层的指针last,nlast将二叉树从上到下,从左到右进行遍历,每一层放入到list中,左后对得到的list<list>进行遍历,将list间隔地从左到右和从右到左放入到新的list中(即对偶数个list从后万千遍历放入到新的list中),然后返回结果list即可。这样做是对结果进行了重新处理,可行,但是没哟充分利用“之字形”的特点来解决问题。

方法二:很巧妙,需要充分理解之字形遍历的特点。可以使用2个栈来解决问题,2个栈交替工作可以做到之字形输出。创建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,通对其的奇偶性判断来决定使用哪一段代码即可。

这里注意,使用2个栈进行层遍历后可以自动对层进行识别,当stack1遍历完后就表示一层的遍历结束了,于是并不需要手动的设置和调整指针last和nlast来识别分层。

 

importjava.util.*;

//之字形遍历:使用2个栈,遍历先压入左结点再压入右结点和先右结点再左结点交替进行;自动换行,不用lastnlast

publicclass Solution {

   //创建结果集,成员变量

    ArrayList<ArrayList<Integer>>results;

    publicArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {

        results=newArrayList<ArrayList<Integer>>();

       //特殊输入

        if(pRoot==null) return results;

       //调用方法解决问题

        this.process(pRoot);

       //返回结果集

        return results;

    }

   

   //该方法用来之字形遍历二叉树,并将每层结果放入到results

    private void process(TreeNode root){

       //①创建辅助栈

        Stack<TreeNode> stack1=newStack<>();

        Stack<TreeNode> stack2=newStack<>();

       //每一层的结果集

        ArrayList<Integer> list=newArrayList<>();

       //第一变量记录层数

        int levelCount=1;

       //②先将root压入栈

        stack1.push(root);

       //③循环:弹栈遍历--左右孩子入栈--交换stack1stack2

       //只要stack1stack2不全为空就可以继续

       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,stack1stack2;层数加1

                results.add(list);

                list=newArrayList<Integer>();

                stack1=stack2;

                stack2=newStack<TreeNode>();

                //千万记得层数+1

                levelCount++;

            }

        }

    }

}

 

几个常识:

队列LinkedList中添加使用add(),弹出使用poll();

栈Stack中入栈用push(),出栈用pop();  记:观众站着听流行音乐

遍历时结果集合中通常存放的是Integer而不是TreeNode,因此是ArrayList<Integer>

取余运算符是%,而/是取整的运算符,不要弄错,没有mod。
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 vivo触屏不灵敏怎么办 中兴手机分屏触屏失灵怎么办 三星a7屏幕发红怎么办 手主板坏了怎么办 三星s7后屏碎了怎么办 三星s4相机故障怎么办 mate10屏幕碎了怎么办 mate9屏幕碎了怎么办 一体机屏幕碎了怎么办 华为p20后屏碎了怎么办 华为手机屏摔碎了怎么办 红米手机屏幕失灵怎么办 电池胶拉断了怎么办 屏保密码忘记了怎么办 手机卡注销了钱怎么办 信用卡号码换了怎么办 网上选牌照失效怎么办 银行卡身份证过期了怎么办 高铁忘带身份证怎么办 动车临时身份证怎么办 身份证丢了怎么办登机 儿童身份证丢了怎么办 临时身份证贷不了怎么办 16岁以下怎么办银行卡 身份证钱包丢了怎么办 社保卡同步自己怎么办 扬州市民(副卡)怎么办 北京医保存折怎么办卡 洛阳新医保卡怎么办 身份证丢了怎么办社保 南京社保卡个人怎么办 文登急用社保卡怎么办 临时医保卡丢失怎么办 外地儿童怎么办社保卡 给孩子怎么办社保卡 铁路社保卡丢失怎么办 医保社保卡遗失怎么办 更换医保卡需要怎么办 卡号记不住丢了怎么办 铁路医保卡丢失怎么办? 异地工作调动公积金怎么办