剑指Offer对答如流系列 - 从上往下打印二叉树

Posted jefferychenxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer对答如流系列 - 从上往下打印二叉树相关的知识,希望对你有一定的参考价值。

面试题32:从上往下打印二叉树

题目描述

树的结构定义如下:

public class Node{
        int e;
        Node left;
        Node right;
        Node(int x) { e = x; }
    }

(一)不分行从上到下打印二叉树

从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。

比如下面二叉树,输出顺序为 8 6 10 5 7 9 11
技术图片

(二)分行从上到下打印二叉树

从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印到一行。

比如下面二叉树,输出顺序为

8

6 10

5 7 9 11

技术图片

(三)之字形打印二叉树

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

比如下面二叉树,输出顺序为

8

10 6

5 7 9 11

技术图片

二、问题分析

三个问题循序渐进。

我们首先看第一个,这个很明显就是层序遍历,结点满足先进先出的原则,采用队列。每从队列中取出头部结点并打印,若其有子结点,把子结点放入队列尾部,直到所有结点打印完毕。

关于树的层序遍历我们早就探讨过了 剑指Offer对答如流系列 - 重建二叉树

第二个问题的解决很明显建立在第一个问题的解决方法基础上,因为要按行打印,依据树的特点,我们需要增加两个变量:当前层结点数目pCount,下一层结点数目nextCount。根据当前层结点数目来打印当前层结点,同时计算下一层结点数目,之后令pCount等于nextCount,重复循环,直到打印完毕。

第三个问题的解决很明显建立在第二个问题的解决方法基础上,因为涉及到逆序输出,我们可以用两个栈。对于不同层的结点,一个栈用于正向存储,一个栈用于逆向存储,打印出来就正好是相反方向。

除了这种思路之外,我们也可以多定义一个表示当前层数的变量level。每层结点不直接打印,放入一个数组中,根据此时的层数level的奇偶来决定正向还是反向打印数组。

三、问题解答

(1)不分行从上到下打印二叉树

因为链表删除和添加元素 速度非常快,选择使用链表实现栈。

 public void printTree(Node root) {
        if (root == null) {
            return;
        }
        LinkedList<Node> queue = new LinkedList<>();
        queue.offer(root);
        Node node;
        while (queue.size()!=0) {
            node = queue.poll();
            System.out.print(node.e + " ");
            if (node.left != null)
                queue.offer(node.left);
            if (node.right != null)
                queue.offer(node.right);
        }
        System.out.println();
    }

(2)分行从上到下打印二叉树

    public void printTree(Node root) {
        if (root == null) {
            return;
        }
        LinkedList<Node> queue = new LinkedList<>();
        queue.offer(root);
        Node node = null;
        int pCount;      //当前层结点数目
        int nextCount = 1;   //下一层结点数目
        while (!queue.isEmpty()) {
            pCount = nextCount;
            nextCount = 0;
            //打印当前层数字,并计算下一层结点数目
            for (int i = 1; i <= pCount; i++) {
                node = queue.poll();
                System.out.print(node.e + " ");
                if (node.left != null) {
                    queue.offer(node.left);
                    nextCount++;
                }
                if (node.right != null) {
                    queue.offer(node.right);
                    nextCount++;
                }
            }
            System.out.println();
        }
    }

(3)之字形打印二叉树

思路1

  public void printTree(Node root) {
        if (root == null) {
            return;
        }
        
        Stack<Node> stack1 = new Stack<>();
        Stack<Node> stack2 = new Stack<>();
        Node node;
        stack1.push(root);
        while(!stack1.empty() || !stack2.empty()) {
            while(!stack1.empty()) {
                node=stack1.pop();
                System.out.print(node.e + " ");
                if (node.left != null)
                    stack2.push(node.left);
                if (node.right != null)
                    stack2.push(node.right);
            }
            System.out.println();
            while(!stack2.empty()) {
                node=stack2.pop();
                System.out.print(node.e + " ");
                if (node.right != null)
                    stack1.push(node.right);
                if (node.left != null)
                    stack1.push(node.left);
            }
            System.out.println();
        }
    }

思路2

  public void printTree(Node root) {
        if (root == null) {
            return;
        }

        LinkedList<Node> queue = new LinkedList<>();
        queue.offer(root);
        Node node;
        int pCount;      //当前层结点数目
        int nextCount = 1;   //下一层结点数目
        int level=1;    //层数
        int[] pNums;    //用于存储当前层的数字
        while (!queue.isEmpty()) {
            pCount = nextCount;
            nextCount = 0;
            pNums=new int[pCount];
            //存储当前层数字,并计算下一层结点数目
            for (int i = 0; i < pCount; i++) {
                node = queue.poll();
                pNums[i]=node.e;
                if (node.left != null) {
                    queue.offer(node.left);
                    nextCount++;
                }
                if (node.right != null) {
                    queue.offer(node.right);
                    nextCount++;
                }
            }
            //根据当前层数确定正向或者反向打印数组
            if( (level&1) != 0 ) {
                for(int i=0; i<pCount; i++) {
                    System.out.print(pNums[i]+" ");
                }
            } else {
                for(int i=pCount-1; i>=0; i--) {
                    System.out.print(pNums[i]+" ");
                }
            }
            level++;
            System.out.println();
        }
    }

以上是关于剑指Offer对答如流系列 - 从上往下打印二叉树的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer-从上往下打印二叉树

剑指offer 22. 从上往下打印二叉树

剑指Offer:从上往下打印二叉树

剑指offer---从上往下打印二叉树

从上往下打印二叉树-剑指Offer

剑指 offer-从上往下打印二叉树