《剑指offer》刷题——【举例让抽象问题具体化】面试题32:从上到下打印二叉树(java实现)

《剑指offer》刷题——【举例让抽象问题具体化】面试题32:从上到下打印二叉树(java实现)

一、题目描述

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

二、题目分析

  • 借助队列
  • 每次打印一个节点的时候,如果该节点有子节点,则把该节点的子节点放到一个队列的末尾;
  • 然后到队列的头部取出最早进入队列的节点
  • 重复上述操作,直至队列中所有的节点都被打印出来
    在这里插入图片描述

三、代码实现

import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

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

    }

}
*/
public class Solution { 
    /**
    * 二叉树的层次遍历
    */
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
    	//存放结果集
        ArrayList<Integer> list = new ArrayList<Integer>();
        //空树
        if(root==null){
            return list;
        }
        //定义一个队列,保存遍历节点
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        //入队
        queue.offer(root); 
        //若队不为空
        while(!queue.isEmpty()){
            //出队
            TreeNode treeNode = queue.poll();
            //左节点不为空
            if(treeNode.left != null){
                //左节点入队
                queue.offer(treeNode.left);
            }
            //右节点不为空
            if(treeNode.right != null){
                //右节点入队
                queue.offer(treeNode.right);
            }
            //将遍历到的节点添加到结果集中
            list.add(treeNode.val);
        }
        return list;
    }
}

四、题目扩展

  • 分行打印二叉树
  • 之字形打印二叉树
package binaryTree;
/**
 * @Description: 三种不同形式的二叉树打印
 * @Author: hw
 * @Date: 2019/7/1 13:48
 */
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val){
        this.val = val;
    }
}
package binaryTree;

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

/**
 * @Description:
 * @Author: hw
 * @Date: 2019/7/1 13:50
 */
public class printBinaryTree {

    /**
     * 层次遍历:不分行从上到下打印二叉树
     */
    public ArrayList<Integer> printFromTopToButtom(TreeNode root){
        ArrayList<Integer> list = new ArrayList<Integer>();
        //用LinkedList实现队列,可调用add offer element peek poll等方法
        Queue<TreeNode> queue = new LinkedList<TreeNode>();

        //队列判空
        if(root==null){
            return null;
        }
        //根节点入队
        queue.offer(root);
        //队不为空
        while(queue.size() != 0){
            //出队一个元素
            TreeNode tmp = queue.poll();
            //左节点入队
            if(tmp.left != null){
                queue.offer(tmp.left);
            }
            //右节点入队
            if(tmp.right != null){
                queue.offer(tmp.right);
            }
            //将出队的元素加入到返回list中
            list.add(tmp.val);
        }
       return list;
    }

    /**
     * 分行从上到下打印二叉树
     * 需要两个变量:记录当前行未打印节点数;记录下一行需要打印的节点数
     */
    public void printTreeSplitRow(TreeNode root){
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        if (root==null){
            return;
        }
        //1. 将根节点放入队列
        queue.offer(root);

        int nextLevel = 0;//下一层节点数
        int toBePrint = 1; //当前行未打印节点数

        while(!queue.isEmpty()){
            //2. 从队列头部取出一个节点
            TreeNode tmp = queue.poll();
            //打印当前节点
            System.out.print(tmp.val + " ");

            //3. 如果一个节点有子节点,则把每一个子节点加入队列,同时吧nextLevel加一
            if (tmp.left != null){
                queue.add(tmp.left);
                nextLevel++;
            }
            if(tmp.right != null){
                queue.add(tmp.right);
                nextLevel++;
            }
            //4. 每打印一个节点,当前层待打印节点数减一
            toBePrint--;
            //若当前行剩余打印节点数为0,表示当前行已经打印完毕,开始下一行
            if(toBePrint==0){
                System.out.println();
                toBePrint = nextLevel;
                nextLevel = 0;
            }
        }

    }


    /**
     * 之字形打印二叉树
     * 需要两个辅助栈实现各行反序
     * 交替使用两个栈,奇数层数据放在stack1,偶数层数据放在stack2
     * 奇数层把下一层数据先左后右压入stack2,偶数层把下一层先右后左压入stack1
     */
    public void printTree(TreeNode root){
        if (root==null)
            return;

        ArrayList<TreeNode> stack1 = new ArrayList<>();
        ArrayList<TreeNode> stack2 = new ArrayList<>();

        boolean isOdd = true;//是否为奇数层
        TreeNode tmp = null;
        //根节点入栈1
        stack1.add(root);
        while(!stack1.isEmpty() || !stack2.isEmpty()){

            /**
             * 打印当前行
             */
            //奇数层
            if(isOdd){
                //取出栈顶元素,并弹出
                tmp = stack1.get(stack1.size()-1);
                stack1.remove(stack1.size()-1);
            }
            //偶数层
            else {
                tmp = stack2.get(stack2.size()-1);
                stack2.remove(stack2.size()-1);
            }
            System.out.print(tmp.val + " ");

            /**
             * 保存下一行
             */
            //奇数层,将下一层先左后右的保存至stack2
            if (isOdd){
                if (tmp.left != null){
                    stack2.add(tmp.left);
                }
                if (tmp.right != null){
                    stack2.add(tmp.right);
                }
            }
            //偶数层,将下一层先右后左的保存至stack1
            else{
                if (tmp.right != null){
                    stack1.add(tmp.right);
                }
                if (tmp.left != null){
                    stack1.add(tmp.left);
                }
            }

            /**
             * 一行结束,更改行标记
             */
            //当前层打印完毕,换行,并更改isOdd的值
            if (isOdd){
                if (stack1.isEmpty()){
                    System.out.println();
                    isOdd = !isOdd;
                }
            }
            else {
                if (stack2.isEmpty()){
                    System.out.println();
                    isOdd = !isOdd;
                }
            }
        }
    }
}

package binaryTree;

import java.util.ArrayList;

/**
 * @Description: 二叉树打印测试类
 * @Author: hw
 * @Date: 2019/7/1 14:14
 */
public class TestBinaryTree {
    public static void main(String[] args) {
        TreeNode node1 = new TreeNode(8);
        TreeNode node2 = new TreeNode(6);
        TreeNode node3 = new TreeNode(10);
        TreeNode node4 = new TreeNode(5);
        TreeNode node5 = new TreeNode(7);
        TreeNode node6 = new TreeNode(9);
        TreeNode node7 = new TreeNode(11);

        node1.left = node2;
        node1.right = node3;
        node2.left = node4;
        node2.right = node5;
        node3.left = node6;
        node3.right = node7;

        printBinaryTree printBinaryTree = new printBinaryTree();
        ArrayList<Integer> list = printBinaryTree.printFromTopToButtom(node1);
        System.out.println("====================不分行打印========================================");
        for (Integer i: list) {
            System.out.print(i + " ");
        }
        System.out.println();
        System.out.println("====================分行打印========================================");
        printBinaryTree.printTreeSplitRow(node1);
        System.out.println("====================之字形打印========================================");
        printBinaryTree.printTree(node1);

    }
}

参考博文

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值