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

题目:

不分行从上到下打印二叉树。

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

分析:

这里就是按照层次遍历,我们需要一个队列来辅助完成遍历。

每次打印一个结点的时候,如果该结点有子结点,则把该结点的子结点放到一个队列的末尾。接下来到队列的头部取出最早进入队列的结点,重复前面的打印操作,直至队列中所有的结点都被打印出来。

解法:

package com.wsy;

import java.util.LinkedList;
import java.util.Queue;

class Tree {
    private int value;
    private Tree left;
    private Tree right;

    public Tree() {
    }

    public Tree(int value) {
        this.value = value;
        this.left = this.right = null;
    }

    public Tree(int value, Tree left, Tree right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Tree getLeft() {
        return left;
    }

    public void setLeft(Tree left) {
        this.left = left;
    }

    public Tree getRight() {
        return right;
    }

    public void setRight(Tree right) {
        this.right = right;
    }
}

public class Main {
    public static void main(String[] args) {
        Tree tree = init();
        print(tree);
    }

    public static Tree init() {
        Tree tree1 = new Tree(8);
        Tree tree2 = new Tree(6);
        Tree tree3 = new Tree(10);
        Tree tree4 = new Tree(5);
        Tree tree5 = new Tree(7);
        Tree tree6 = new Tree(9);
        Tree tree7 = new Tree(11);
        tree1.setLeft(tree2);
        tree1.setRight(tree3);
        tree2.setLeft(tree4);
        tree2.setRight(tree5);
        tree3.setLeft(tree6);
        tree3.setRight(tree7);
        return tree1;
    }

    public static void print(Tree tree) {
        if (tree == null) {
            return;
        }
        Queue<Tree> queue = new LinkedList<Tree>();
        queue.add(tree);
        while (!queue.isEmpty()) {
            tree = queue.poll();
            System.out.print(tree.getValue() + "\t");
            if (tree.getLeft() != null) {
                queue.add(tree.getLeft());
            }
            if (tree.getRight() != null) {
                queue.add(tree.getRight());
            }
        }
    }
}

题目:

分行从上到下打印二叉树。

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

分析:

我们需要加入两个变量:一个变量表示当前层中还没有打印的结点数,另一个变量表示下一层结点的数目。

变量toBePrint表示当前层还没有打印的结点数,变量nextLevel表示下一层的结点数。如果一个结点有子结点,每把一个子结点加入队列,同时把变量nextLevel加1。每打印一个结点,toBePrint减1。当toBePrint变成0时,表示当前层的所有结点已经打印完毕,可以继续打印下一层了。

解法:

package com.wsy;

import java.util.LinkedList;
import java.util.Queue;

class Tree {
    private int value;
    private Tree left;
    private Tree right;

    public Tree() {
    }

    public Tree(int value) {
        this.value = value;
        this.left = this.right = null;
    }

    public Tree(int value, Tree left, Tree right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Tree getLeft() {
        return left;
    }

    public void setLeft(Tree left) {
        this.left = left;
    }

    public Tree getRight() {
        return right;
    }

    public void setRight(Tree right) {
        this.right = right;
    }
}

public class Main {
    public static void main(String[] args) {
        Tree tree = init();
        print(tree);
    }

    public static Tree init() {
        Tree tree1 = new Tree(8);
        Tree tree2 = new Tree(6);
        Tree tree3 = new Tree(10);
        Tree tree4 = new Tree(5);
        Tree tree5 = new Tree(7);
        Tree tree6 = new Tree(9);
        Tree tree7 = new Tree(11);
        tree1.setLeft(tree2);
        tree1.setRight(tree3);
        tree2.setLeft(tree4);
        tree2.setRight(tree5);
        tree3.setLeft(tree6);
        tree3.setRight(tree7);
        return tree1;
    }

    public static void print(Tree tree) {
        if (tree == null) {
            return;
        }
        Queue<Tree> queue = new LinkedList<Tree>();
        queue.add(tree);
        int nextLevel = 0;
        int toBePrint = 1;
        while (!queue.isEmpty()) {
            tree = queue.poll();
            System.out.print(tree.getValue() + "\t");
            if (tree.getLeft() != null) {
                queue.add(tree.getLeft());
                nextLevel++;
            }
            if (tree.getRight() != null) {
                queue.add(tree.getRight());
                nextLevel++;
            }
            toBePrint--;
            if (toBePrint == 0) {
                System.out.println("");
                toBePrint = nextLevel;
                nextLevel = 0;
            }
        }
    }
}

题目:

之字形打印二叉树。

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

分析:

当二叉树根节点1打印之后,它的左结点2和右结点3先后保存到一个数据容器里。在打印第二层结点时,先打印结点3,再打印结点2。因此这个数据容器可以用栈来实现。

在打印第三层的时候,先打印2的子结点(结点4和结点5),再打印结点3的子结点(结点6和结点7),结点4,5和结点6,7对于结点3,结点2也是反着的,所以也可以用栈来实现。用一个栈保存结点2和结点3的子结点。

第三层结点是从左向右打印的,按照4->5->6->7的顺序,所以7先入栈,接着是6,5,4。在打印第二层结点的时候,先把右子结点保存到栈里,再把左子结点保存到栈里。

打印第三层结点的同时,需要把第四层结点保存到一个栈里。由于第四层的打印顺序是从右到左,因此保存的顺序是先保存左子结点,再保存右子结点。

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

如果这里只用一个栈,打印根节点时候,先后把结点2,结点3保存到栈中。接下来打印结点3,会把结点6,结点7保存到栈中,此时,结点7就位于栈顶了,而不是结点2,此时就乱了。

解法:

package com.wsy;

import java.util.Stack;

class Tree {
    private int value;
    private Tree left;
    private Tree right;

    public Tree() {
    }

    public Tree(int value) {
        this.value = value;
        this.left = this.right = null;
    }

    public Tree(int value, Tree left, Tree right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Tree getLeft() {
        return left;
    }

    public void setLeft(Tree left) {
        this.left = left;
    }

    public Tree getRight() {
        return right;
    }

    public void setRight(Tree right) {
        this.right = right;
    }
}

public class Main {
    public static void main(String[] args) {
        Tree tree = init();
        print(tree);
    }

    public static Tree init() {
        Tree tree15 = new Tree(15);
        Tree tree14 = new Tree(14);
        Tree tree13 = new Tree(13);
        Tree tree12 = new Tree(12);
        Tree tree11 = new Tree(11);
        Tree tree10 = new Tree(10);
        Tree tree9 = new Tree(9);
        Tree tree8 = new Tree(8);
        Tree tree7 = new Tree(7, tree14, tree15);
        Tree tree6 = new Tree(6, tree12, tree13);
        Tree tree5 = new Tree(5, tree10, tree11);
        Tree tree4 = new Tree(4, tree8, tree9);
        Tree tree3 = new Tree(3, tree6, tree7);
        Tree tree2 = new Tree(2, tree4, tree5);
        Tree tree1 = new Tree(1, tree2, tree3);
        return tree1;
    }

    public static void print(Tree tree) {
        if (tree == null) {
            return;
        }
        Stack<Tree> stack0 = new Stack<>();
        Stack<Tree> stack1 = new Stack<>();
        boolean odd = true;
        stack1.push(tree);
        while (!stack0.empty() || !stack1.empty()) {
            if (odd) {
                tree = stack1.pop();
                System.out.print(tree.getValue() + "\t");
                if (tree.getLeft() != null) {
                    stack0.push(tree.getLeft());
                }
                if (tree.getRight() != null) {
                    stack0.push(tree.getRight());
                }
                if (stack1.empty()) {
                    odd = !odd;
                    System.out.println();
                }
            } else {
                tree = stack0.pop();
                System.out.print(tree.getValue() + "\t");
                if (tree.getRight() != null) {
                    stack1.push(tree.getRight());
                }
                if (tree.getLeft() != null) {
                    stack1.push(tree.getLeft());
                }
                if (stack0.empty()) {
                    odd = !odd;
                    System.out.println();
                }
            }
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值