按之字形顺序打印二叉树
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) 收藏 举报
浙公网安备 33010602011771号