粗鲁分析:
二叉树的按层遍历是这样:从左到右,从上到下访问每个节点。而二叉树本身给出的信息是其下一行的左右节点的,所以在访问某一行节点时,就要保存其含有的信息——下一行节点。
如果某行有n个节点,从1访问到n时,需要保存1的左右节点,2的左右节点,,,n的左右节点,遍历下行时的顺序是1的左右,2的左右,,,n的左右。
这不就是先进(先保存)先出(先访问)吗?
算法伪码:
1.root进队(每个元素都要进队,别直接访问)
2.开始循环:队首出队,其左右节点进队。(当然你也可以左右节点先进队,再队首出队,但是这样比较不舒服!——老子还没出去,儿子就进来了)
循环条件是队非空。
简单的代码:
public void visitTree(TreeNode root) { Queue<TreeNode> queue = new LinkedList<TreeNode>(); queue.offer(root); TreeNode cur; while(!queue.isEmpty()) { cur = queue.poll();//出队 System.out.println(cur.val);//访问这个出队的 if (cur.left != null) { queue.offer(cur.left); nlast = cur.left; } if (cur.right != null) { queue.offer(cur.right); nlast = cur.right; } } }=======================分割线===================================
然鹅,事情并不总是这么简单。现在要求在每行结束后打印换行,该如何?
第一行的换行很简单啊,root后直接换行。
那么你已经知道了第一行的换行,你就知道了第二行的换行位置啊,毕竟第二行都是第一行的“映射”
所以呢,跟刚才一样,在访问第n行的时候就要保存第n+1行的最右信息,反正n+1行的最右就是从第n行的左节点(第n+1行的最左)开始迭代。
-----
现在需要2个变量,一个保存当前行的最右设为last,一个保存下一行的最右nlast。
last刚开始为root,当前行即第一行,第一行最右即root,已知的最右,没毛病
当访问到cur==last时,打印换行,且此时nlast必定已经迭代到下一行的最右了,所以在把nlast赋给last,进入下一行的访问。
代码依旧很简单
public void visitTree(TreeNode root) { Queue<TreeNode> queue = new LinkedList<TreeNode>(); queue.offer(root); TreeNode cur; TreeNode last = root; //当前行的最后一个节点——初始值,root TreeNode nlast; //下一行的最后一个节点 while(!queue.isEmpty()) { cur = queue.poll(); System.out.println(cur.val); if (cur.left != null) { queue.offer(cur.left); nlast = cur.left;//迭代的nlast } if (cur.right != null) { queue.offer(cur.right); nlast = cur.right;//迭代的nlast } if (cur == last) {//当前节点是当前最右时,nlast的迭代也就结束了,它已经是最右了,赋给last System.out.println("---------");//直接都用println了,用----假装换行,重在思路,不要在意细节 last = nlast; }//这个判断为什么要放到左右节点进队之后呢,因为还要迭代nlast呢,很关键 } }