本文参考自《剑指offer》一书,代码采用Java语言。

更多:《剑指Offer》Java实现合集  

题目 

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

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

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

思路

  (一)不分行从上往下打印二叉树:该题即为对二叉树的层序遍历,结点满足先进先出的原则,采用队列。每从队列中取出头部结点并打印,若其有子结点,把子结点放入队列尾部,直到所有结点打印完毕。

	/*
* 不分行从上往下打印二叉树
*/
// 题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。
public void printTree1(TreeNode root) {
if (root == null)
return;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
TreeNode node = null;
while (queue.size()!=0) {
node = queue.poll();
System.out.print(node.val + " ");
if (node.left != null)
queue.offer(node.left);
if (node.right != null)
queue.offer(node.right);
}
System.out.println();
}

  (二)分行从上到下打印二叉树:同样使用队列,但比第一题增加两个变量:当前层结点数目pCount,下一层结点数目nextCount。根据当前层结点数目来打印当前层结点,同时计算下一层结点数目,之后令pCount等于nextCount,重复循环,直到打印完毕。

	/*
* 分行从上到下打印二叉树
*/
// 题目:从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层
// 打印到一行。
public void printTree2(TreeNode root) {
if (root == null)
return;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
TreeNode node = null;
int pCount = 0; //当前层结点数目
int nextCount = 1; //下一层结点数目
while (!queue.isEmpty()) {
pCount = nextCount;
nextCount = 0;
//打印当前层数字,并计算下一层结点数目
for (int i = 1; i <= pCount; i++) {
node = queue.poll();
System.out.print(node.val + " ");
if (node.left != null) {
queue.offer(node.left);
nextCount++;
}
if (node.right != null) {
queue.offer(node.right);
nextCount++;
}
}
System.out.println();
}
}

  (三)之字形打印二叉树:

    (1)自己开始想的方法:在(二)的基础上,多定义一个表示当前层数的变量level。每层结点不直接打印,放入一个数组中,根据此时的层数level的奇偶来决定正向还是反向打印数组。

	/*
* 之字形打印二叉树
*/
// 题目:请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺
// 序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,
// 其他行以此类推。
/**
* 自己开始想的方法,采用数组存储每层的数字,根据当前层数确定正反向打印数组
*/
public void printTree3_1(TreeNode root) {
if (root == null)
return;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
TreeNode node = null;
int pCount = 0; //当前层结点数目
int nextCount = 1; //下一层结点数目
int level=1; //层数
int[] pNums=null; //用于存储当前层的数字
while (!queue.isEmpty()) {
pCount = nextCount;
nextCount = 0;
pNums=new int[pCount];
//存储当前层数字,并计算下一层结点数目
for (int i = 0; i < pCount; i++) {
node = queue.poll();
pNums[i]=node.val;
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();
}
}

    (2)书中提供的方法:采用两个栈,对于不同层的结点,一个栈用于正向存储,一个栈用于逆向存储,打印出来就正好是相反方向。

	/**
* 采用两个栈进行操作的方法
*/
public void printTree3_2(TreeNode root) {
if (root == null)
return;
Stack<TreeNode> stack1 = new Stack<TreeNode>();
Stack<TreeNode> stack2 = new Stack<TreeNode>();
TreeNode node = null;
stack1.push(root);
while(!stack1.empty() || !stack2.empty()) {
while(!stack1.empty()) {
node=stack1.pop();
System.out.print(node.val + " ");
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.val + " ");
if (node.right != null)
stack1.push(node.right);
if (node.left != null)
stack1.push(node.left);
}
System.out.println();
}
}

  

测试算例 

  1.功能测试(完全二叉树;左斜树;右斜树)

  2.特殊测试(null;一个结点)

完整Java代码

含测试代码:

import java.util.LinkedList;
import java.util.Stack;
/**
*
* @Description 面试题32:从上往下打印二叉树
*
* @author yongh
*/ public class PrintTreeFromTopToBottom {
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null; public TreeNode(int val) {
this.val = val;
}
} /*
* 不分行从上往下打印二叉树
*/
// 题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。
public void printTree1(TreeNode root) {
if (root == null)
return;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
TreeNode node = null;
while (queue.size()!=0) {
node = queue.poll();
System.out.print(node.val + " ");
if (node.left != null)
queue.offer(node.left);
if (node.right != null)
queue.offer(node.right);
}
System.out.println();
} /*
* 分行从上到下打印二叉树
*/
// 题目:从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层
// 打印到一行。
public void printTree2(TreeNode root) {
if (root == null)
return;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
TreeNode node = null;
int pCount = 0; //当前层结点数目
int nextCount = 1; //下一层结点数目
while (!queue.isEmpty()) {
pCount = nextCount;
nextCount = 0;
//打印当前层数字,并计算下一层结点数目
for (int i = 1; i <= pCount; i++) {
node = queue.poll();
System.out.print(node.val + " ");
if (node.left != null) {
queue.offer(node.left);
nextCount++;
}
if (node.right != null) {
queue.offer(node.right);
nextCount++;
}
}
System.out.println();
}
} /*
* 之字形打印二叉树
*/
// 题目:请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺
// 序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,
// 其他行以此类推。
/**
* 自己开始想的方法,采用数组存储每层的数字,根据当前层数确定正反向打印数组
*/
public void printTree3_1(TreeNode root) {
if (root == null)
return;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
TreeNode node = null;
int pCount = 0; //当前层结点数目
int nextCount = 1; //下一层结点数目
int level=1; //层数
int[] pNums=null; //用于存储当前层的数字
while (!queue.isEmpty()) {
pCount = nextCount;
nextCount = 0;
pNums=new int[pCount];
//存储当前层数字,并计算下一层结点数目
for (int i = 0; i < pCount; i++) {
node = queue.poll();
pNums[i]=node.val;
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();
}
} /**
* 采用两个栈进行操作的方法
*/
public void printTree3_2(TreeNode root) {
if (root == null)
return;
Stack<TreeNode> stack1 = new Stack<TreeNode>();
Stack<TreeNode> stack2 = new Stack<TreeNode>();
TreeNode node = null;
stack1.push(root);
while(!stack1.empty() || !stack2.empty()) {
while(!stack1.empty()) {
node=stack1.pop();
System.out.print(node.val + " ");
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.val + " ");
if (node.right != null)
stack1.push(node.right);
if (node.left != null)
stack1.push(node.left);
}
System.out.println();
}
} //============测试代码==============
private void test(int testNum,TreeNode root) {
System.out.println("=========test"+testNum+"===========");
System.out.println("method1:");
printTree1(root);
System.out.println("method2:");
printTree2(root);
System.out.println("method3_1:");
printTree3_1(root);
System.out.println("method3_2:");
printTree3_2(root);
} //null
private void test1() {
TreeNode node=null;
test(1, node);
} //单个结点
private void test2() {
TreeNode node=new TreeNode(1);
test(2, node);
} //左斜
private void test3() {
TreeNode node1=new TreeNode(1);
TreeNode node2=new TreeNode(2);
TreeNode node3=new TreeNode(3);
node1.left=node2;
node2.left=node3;
test(3, node1);
} //右斜
private void test4() {
TreeNode node1=new TreeNode(1);
TreeNode node2=new TreeNode(2);
TreeNode node3=new TreeNode(3);
node1.right=node2;
node2.right=node3;
test(4, node1);
} //完全二叉树
private void test5() {
TreeNode[] nodes = new TreeNode[15];
for(int i=0;i<15;i++) {
nodes[i]= new TreeNode(i+1);
}
for(int i=0;i<7;i++) {
nodes[i].left=nodes[2*i+1];
nodes[i].right=nodes[2*i+2];
}
test(5, nodes[0]);
} public static void main(String[] args) {
PrintTreeFromTopToBottom demo= new PrintTreeFromTopToBottom();
demo.test1();
demo.test2();
demo.test3();
demo.test4();
demo.test5();
}
}

  

=========test1===========
method1:
method2:
method3_1:
method3_2:
=========test2===========
method1: method2: method3_1: method3_2: =========test3===========
method1: method2: method3_1: method3_2: =========test4===========
method1: method2: method3_1: method3_2: =========test5===========
method1: method2: method3_1: method3_2:

PrintTreeFromTopToBottom

收获

  1.层序遍历时,一般都要用到队列,可以用LinkedList类(方法:poll() 和 offer(Obj) )。

  2.在分行打印时,定义的两个int有明显实际意义(当前层结点数目,下一层结点数目)。自己编程时,一开始只知道要设置两个变量,但没有去想这两个变量的实际意义。当明白变量意义时,自己的思路会更清晰,而且代码可读性也更好。

  

更多:《剑指Offer》Java实现合集  

  

【Java】 剑指offer(32) 从上往下打印二叉树的更多相关文章

  1. 剑指offer——32从上到下打印二叉树

    题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印.   题解: 就是简单的层序遍历 class Solution { public: vector<int> PrintFro ...

  2. 《剑指offer》从上往下打印二叉树

    本题来自<剑指offer> 从上往下打印二叉树 题目: 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 思路: 队列的思想. 先将根节点加入,当取该节点时候,依次将左右子树加入,直 ...

  3. 【剑指Offer】从上往下打印二叉树 解题报告(Python)

    [剑指Offer]从上往下打印二叉树 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews ...

  4. 剑指offer系列20--从上到下打印二叉树

    * 20 [题目]从上往下打印出二叉树的每个节点,同层节点从左至右打印. * [思路]从根结点开始,先保存结点,再看根结点的左右结点有没有值. * 有,就将左右值放到集合中: * 根节点输出后,打印根 ...

  5. 剑指Offer 22. 从上往下打印二叉树 (二叉树)

    题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 题目地址 https://www.nowcoder.com/practice/7fe2212963db4790b57431d9ed25 ...

  6. 【剑指offer】从上向下打印二叉树

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/26089165 剑指offer上的第23题,实际上就是考察二叉树的层序遍历,详细思想能够參考 ...

  7. Go语言实现:【剑指offer】从上往下打印二叉树

    该题目来源于牛客网<剑指offer>专题. 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 不需分层,一维数组. Go语言实现: /** * Definition for a bi ...

  8. 剑指OFFER之从上往下打印二叉树(九度OJ1523)

    题目描述: 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行一个整数n(1<=n<=1000, : ...

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

    题目描述: 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 解题思路: 实际就是二叉树的中序遍历问题.之前在leetcode刷过类似题目. 利用队列完成即可. 代码: /* struct Tr ...

随机推荐

  1. 找第二大的数SQL-Second Highest Salary

    1: 找小于最大的最大的 select max(Salary) from Employee where Salary<(select MAX(Salary) from Employee); 2. ...

  2. JavaScript之创建动态脚本

    //option= {type,src,text,isCreateScriptBySrc} function createDynamicScript(option){ var script = doc ...

  3. 青云VPC网络配置

    1 创建VPC网络 2 申请公网IP 3 回到VPC图形界面绑定公网ip 4 创建私有网络,并绑定私有网络 5 创建3台主机 6 新建防火墙,并绑定到VPC 7 配置VPC端口转发规则 8 添加防火墙 ...

  4. 1.内网ntp服务器的搭建

    1.拓扑图

  5. 重新学习Servlet二

    重新学习Servlet public abstract class HttpServlet extends GenericServlet package com.xh.test.api; import ...

  6. 配置使用OpenCV静态链接库

    配置opencv静态链接库需要用到:staticlib 在配置链接器->附加库目录时应该为staticlib的路径.同理若是利用动态链接库则只需要lib的路径: 动态链接库则使用lib,然而在使 ...

  7. 蓝牙HID协议笔记【转】

    蓝牙HID协议笔记 转自:http://blog.sina.com.cn/s/blog_69b5d2a50101emll.html 1.概述     The Human Interface Devic ...

  8. David McCullough, Jr.为韦斯利高中毕业生演讲〈你并不特别〉

    Dr. Wong, Dr. Keough, Mrs.Novogroski, Ms. Curran, members of the board of education, familyand frien ...

  9. ES系列五、ES6.3常用api之搜索类api

    1.搜索api 1.1.routing:路由 执行搜索时,它将广播到所有索引/索引分片(副本之间的循环).可以通过提供routing参数来控制将搜索哪些分片.例如,在索引book时,路由值可以是nam ...

  10. C++:STL vector:sizeof(vector)

    原文地址:http://blog.csdn.net/zcsylj/article/details/7857009 int的大小是4,定义vector<int> vec,vec中有一个元素, ...