请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
1、用两个栈实现
package test04;
import java.util.ArrayList;
import java.util.Stack;
/* * 注意从第一层开始,每一层的节点都是先进入相应的栈,在出栈,最后按照出栈的顺序,add到每一层的tempList里面 * 再把每一层的tempList add到result中,最终返回 * 例如,从一颗二叉树的根节点开始,因为根节点为第一层,为奇数层。所以先把第一层的根节点push到奇数栈odd里面 * 进入while(当size不等于0时,说明整个二叉树还没有遍历完)循环,判断if条件,此时每次从奇数栈odd中pop,都将该节点 * 的左右子节点按照先左后右的顺序push到偶数栈even中,每循环一次,都要把刚才从奇数栈odd中pop的元素add到这一 * 个的临时tempList中,当stackSize==1时,说明这一层已经遍历完了,此时把每一层的tempList add到reslut中,当while * 条件成立,说明整个二叉树已经遍历完,最终返回result。 * */
public class test05 {
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
if (pRoot == null) {
return result;
}
int stackSize;
boolean isOdd = true;//控制当前遍历的是奇数层还是偶数层
Stack<TreeNode> odd = new Stack<>();//保存奇数层节点的栈
odd.push(pRoot);
Stack<TreeNode> even = new Stack<>();//保存偶数层节点的栈
ArrayList<Integer> tempList = new ArrayList<>();
while (odd.size() != 0 || even.size() != 0) {//说明整个二叉树还没有遍历完
TreeNode root;
if (isOdd) {//假如当前是奇数层,则它的下一层是先保存左子节点,再保存右子节点
stackSize = odd.size();
root = odd.pop();
if (root.left != null) {
even.push(root.left);
}
if (root.right != null) {
even.push(root.right);
}
} else {
stackSize = even.size();
root = even.pop();
if (root.right != null) {
odd.push(root.right);
}
if (root.left != null) {
odd.push(root.left);
}
}
tempList.add(root.val);
if (stackSize == 1) {//Stack不能弹空栈,所以要提前判空,注意因为这个stackSize是在pop之前赋值的,所以判空为==1,
isOdd = !isOdd;//把上一层奇数层遍历完,isOdd设置为false,准备遍历下一层偶数层
result.add(tempList);
tempList = new ArrayList<>();//为每一层创建一个ArrayList对象
}
}
return result;
}
}
2、用LinkList链表实现,因为它是一个双向链表
package test04;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
public class test06 {
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
if (pRoot == null) {
return ret;
}
ArrayList<Integer> list = new ArrayList<>();//list是存每一层的节点
LinkedList<TreeNode> queue = new LinkedList<>();//
queue.addLast(null);// 层分隔符
queue.addLast(pRoot);// 把根节点添加到queue中
boolean leftToRight = true;// 开始的时候从左向右遍历
while (queue.size() != 1) {
TreeNode node = queue.removeFirst();//取出LinkedList中的第一个节点,并将该节点从LinkedList中删除
if (node == null) {// 假如达到层分隔符
Iterator<TreeNode> iter = null;
if (leftToRight) {
iter = queue.iterator();// 从前向后遍历
} else {
iter = queue.descendingIterator();// 从后向前遍历
}
leftToRight = !leftToRight;
while (iter.hasNext()) {// 遍历每一层的节点,存到list集合中
TreeNode temp = (TreeNode)iter.next();//注意这里的细节问题,这里的(TreeNode)可以省略,因为前面声明
//iter的时候已经指定了泛型Iterator的类型为TreeNode假如前面不指定,这里一定要加上
list.add(temp.val);
}
ret.add(new ArrayList<>(list));// 把每一层的list集合存到ret集合中
//ret.add(list);
list.clear();// list集合clear,为存下一层做准备
queue.addLast(null);
continue;//必须要这一句,因为假如node==null,再判断node.lef或者node.right会出现空指针异常
}
if (node.left != null) {
queue.addLast(node.left);
}
if (node.right != null) {
queue.addLast(node.right);
}
}
return ret;
}
}