Z字型打印二叉树

来源:互联网 发布:游戏美工分为什么 编辑:程序博客网 时间:2024/05/21 07:14

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

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;    }}

参考