剑指offer第二版面试题32:从上到下打印二叉树(java)

题目一描述:
从上往下打印二叉树的每个节点,同一层的节点按照从左到右的顺序打印。例如输入下图的二叉树,则一次打印出8,6,10,5,7,9,11。
这里写图片描述

分析:
这道题实质上考察的就是树的遍历算法,只是这种遍历不是我们熟悉的前序、中序或者后序遍历。由于我们不太熟悉这种按层遍历的方法,可能一下也想不清楚遍历的过程。
因为按层打印的顺序决定应该先打印的根节点,所以我们从树的根节点开始分析。为了接下来能够打印8的节点的两个子节点,我们应该在遍历到该节点时把值为6和10的两个节点保存到一个容器中,现在容器内就有两个节点了。按照从左到右打印的要求,我们先取出值为6的节点。打印出6后把它的值分别为5和7的两个节点放入数据容器。此时数据容器中有三个节点,值分别为10,5,7.接下来我们从数据容器中取出值为10的节点。注意到值为10的节点比值为5,7,的节点先放入容器,此时又比这两个节点先取出,这就是我们通常说的先入先出,因此不难看出这个容器应该是一个队列。由于值为5,7,9,11的节点都没有子节点,因此只要依次打印即可。
通过分析具体例子,我们可以找到从上到下打印二叉树的规律:每一次打印一个节点的时候,如果该节点有子节点,把该节点的子节点放到一个队列的尾。接下来到队列的头部取出最早进入队列的节点,重复前面打印操作,直到队列中所有的节点都被打印出为止。

代码如下:

/**
 * 层次遍历
 *  从上到下访问节点,当访问到某一层时,从左到右访问
 */
public class Solution {

    public void fun(TreeNode root){
        if(root == null){
            return ;
        }
        //定义队列
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            //取出队列头部节点
            TreeNode tempNode = queue.poll();
            System.out.print(tempNode.val+"");
            if(tempNode.left != null){
                queue.add(tempNode.left);
            }
            if(tempNode.right != null){
                queue.add(tempNode.right);
            }
        }
    }
}

//二叉树节点
class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }
}

题目二描述:
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印 ,每一层打印一行。

分析:
这道题和前面的题类似,也可以使用一个队列来保存将要打印的节点。为了把二叉树的每一行单独打印到一行里,我们需要两个变量:一个变量表示在当前层中还没有打印的节点数;另一个变量表示下一层节点的数目。

代码如下:

/**
 * 分行从上到下打印二叉树
 */
public class Solution {

    TreeNode flagNode = new TreeNode(-1);

    public void fun1(TreeNode root) {
        if (root == null) {
            return;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        //下一层节点的数量
        int nextLevel = 0;
        //当前层中还没有打印的节点数
        int toBePrinted = 1;

        while (!queue.isEmpty()) {
            TreeNode tempNode = queue.poll();
            System.out.print(tempNode.val + "  ");
            if (tempNode.left != null) {
                queue.add(tempNode.left);
                nextLevel++;
            }
            if (tempNode.right != null) {
                queue.add(tempNode.right);
                nextLevel++;
            }
            toBePrinted--;
            if(toBePrinted == 0){
                System.out.println();
                toBePrinted = nextLevel;
                nextLevel = 0;
            }
        }
    }

    public void fun2(TreeNode root) {
        if(root == null){
            return ;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        queue.add(flagNode);
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            System.out.print(node.val + " ");

            if(node.left != null){
                queue.add(node.left);
            }
            if(node.right != null){
                queue.add(node.right);
            }

            if(queue.peek().val == -1 ){
                queue.poll();
                System.out.println();
                if(!queue.isEmpty()){
                    queue.add(flagNode);
                }
            }
        }
    }
}

题目三描述:
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,即第一行按照从左到右的顺序打印,第二层按照从右到左顺序打印,第三行再按照从左到右的顺序打印,其他以此类推。例如,按之字型打印下图的二叉树结果为:
1
3 2
4 5 6 7
15 14 13 12 11 10 9 8
这里写图片描述

分析:
按之字形顺序打印二叉树需要两个栈。我们在打印某一行结点时,把下一层的子结点保存到相应的栈里。如果当前打印的是奇数层,则先保存左子结点再保存右子结点到一个栈里;如果当前打印的是偶数层,则先保存右子结点再保存左子结点到第二个栈里。

代码如下:

/**
 * 按之字形打印节点
 */
public class Solution {

    public void fun(TreeNode root) {
        if(root == null){
            return ;
        }

        //子节点的加入为:左->右
        Stack<TreeNode> s1 = new Stack<>();     //存储奇数层节点
        //子节点的加入为:右->左
        Stack<TreeNode> s2 = new Stack<>();     //存储偶数层节点
        s1.add(root);

        while(!s1.isEmpty() || !s2.isEmpty()){
            if(s1.isEmpty() && s2.isEmpty()){       //如果两个栈都为空,则退出循环
                break;
            }

            if(!s1.isEmpty()){
                while(!s1.isEmpty()){
                    TreeNode node = s1.pop();
                    System.out.print(node.val+" ");
                    if(node.left != null){
                        s2.add(node.left);
                    }
                    if(node.right != null){
                        s2.add(node.right);
                    }
                }
                System.out.println();
            }else{
                while(!s2.isEmpty()){
                    TreeNode node = s2.pop();
                    System.out.print(node.val+" ");
                    if(node.right != null){
                        s1.add(node.right);
                    }
                    if(node.left != null){
                        s1.add(node.left);
                    }
                }
                System.out.println();
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_37672169/article/details/80449832