面试题32一共包括三个题目。
一、题目一
题目一:不分行从上到下打印二叉树。
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。例如,输入下图1中的二叉树,则依次打印出8,6,10,5,7,9,11。二叉树节点的定义如下:
public class Node {
int data;
Node right;
Node left;
Node(int data) {
this.data = data;
}
}
图一:
1.二叉树的定义
其实题目中的这个例子不是很好,容易让人误解二叉树与二叉排序树的区别。
二叉树的结构是一个父节点挂一个或者两个子节点。
而且我们要注意到。在左右子节点不为空的情况下,若左子节点小于它的父节点,且右子节点大于它的父节点,那是二叉排序树,不是二叉树。在上网查资料的时候有时会看到一些人将其弄混了。
2.算法实现
这是我在学习过程中模仿Java集合类写的一个二叉树类,所以把节点类(Node)以内部类的形式写在二叉树类(BinaryTree)的里面。以Integer类为例,如果引入泛型的话,所有类都可以,欢迎大家指导。
BinaryTree类
import java.util.LinkedList;
public class BinaryTree {
//节点个数
private int size;
//根节点
private Node root;
public BinaryTree() {
}
//有参构造方法
public BinaryTree(Integer[] c) {
this();
root = addAllRecur(c);
}
//前序遍历数据创建二叉树(递归)
private Node addAllRecur(Integer[] c) {
Integer var = c[size++];
if (var == null) {
return null;
}
Node node = new Node(var);
node.left = addAllRecur(c);
node.right = addAllRecur(c);
return node;
}
//层次遍历
public void levelOrder() {
if (root == null) {
return;
}
LinkedList<Node> q = new LinkedList<Node>();
q.addFirst(root);
Node current;
while (!q.isEmpty()) {
current = q.removeLast();
System.out.print(current.data + " -> ");
if (current.left != null)
q.addFirst(current.left);
if (current.right != null)
q.addFirst(current.right);
}
}
private static class Node {
Integer data;
Node right;
Node left;
Node(Integer data) {
this.data = data;
}
}
}
测试类
public class Demo {
public static void main(String[] args) {
//前序遍历建树
Integer[] arr = { 8, 6, 5, null, null, 7, null, null, 10, 9, null, null, 11, null, null };
BinaryTree tree = new BinaryTree(arr);
System.out.print("层次遍历:");
tree.levelOrder();
}
}
建立的树:
测试结果:
层次遍历:8 -> 6 -> 10 -> 5 -> 7 -> 9 -> 11 ->
其实上面内容是我的一篇文章的截取,有兴趣的可以再看看二叉树(从建树、遍历到存储)Java.这里就不再粘贴复制一遍了。
二、题目二
题目二:分行从上到下打印二叉树。
从上到下按层打印二叉树,同一层的节点按左到右的顺序打印,每一层打印到一行。例如,图二中二叉树的结果为:
8
6 10
5 7 9 11
图二:
1.分析
这道面试题和前面的面试题类似,也可以用一个队列来保存将要打印的节点。为了把二叉树的每一行单独打印到一行里,我们需要两个变量:一个变量表示当前层中还没有打印的节点数;另一个变量表示下一层节点的数目。
2.算法实现
依然采用上面的形式,把节点类(Node)写成内部类的形式。
BinaryTree类:
import java.util.LinkedList;
public class BinaryTree {
//节点个数
private int size;
//根节点
private Node root;
public BinaryTree() {
}
//有参构造方法
public BinaryTree(Integer[] c) {
this();
root = addAllRecur(c);
}
//前序遍历数据创建二叉树(递归)
private Node addAllRecur(Integer[] c) {
Integer var = c[size++];
if (var == null) {
return null;
}
Node node = new Node(var);
node.left = addAllRecur(c);
node.right = addAllRecur(c);
return node;
}
//分行层次遍历
public void levelOrder() {
if (root == null) {
return;
}
LinkedList<Node> q = new LinkedList<Node>();
//当前层还没有打印的节点数
int toBePrint = 1;
//下一层节点数
int nextLevel = 0;
q.addFirst(root);
Node current;
while (!q.isEmpty()) {
current = q.removeLast();
System.out.print(current.data + " ");
toBePrint--;
if (current.left != null) {
q.addFirst(current.left);
nextLevel++;
}
if (current.right != null) {
q.addFirst(current.right);
nextLevel++;
}
if (toBePrint == 0) {
System.out.println();
toBePrint = nextLevel;
nextLevel = 0;
}
}
}
private static class Node {
Integer data;
Node right;
Node left;
Node(Integer data) {
this.data = data;
}
}
}
测试类:
public class Demo {
public static void main(String[] args) {
//前序遍历建树
Integer[] arr = { 8, 6, 5, null, null, 7, null, null, 10, 9, null, null, 11, null, null };
BinaryTree tree = new BinaryTree(arr);
System.out.println("分层层次遍历:");
tree.levelOrder();
}
}
建立的树:
测试结果:
分层层次遍历:
8
6 10
5 7 9 11
三、题目三
题目三:之字形打印二叉树。
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二行按照从右到左的顺序打印,第三行在按照从左到右的顺序打印,其他行以此类推。例如,按之字形顺序打印图三中二叉树的结果为:
1
3 2
4 5 6 7
15 14 13 12 11 10 9 8
图三
1.分析
《剑指offer第二版》中是用两个栈实现的。
2.算法实现
BinaryTree类:
import java.util.LinkedList;
public class BinaryTree {
//节点个数
private int size;
//根节点
private Node root;
public BinaryTree() {
}
//有参构造方法
public BinaryTree(Integer[] c) {
this();
root = addAllRecur(c);
}
//前序遍历数据创建二叉树(递归)
private Node addAllRecur(Integer[] c) {
Integer var = c[size++];
if (var == null) {
return null;
}
Node node = new Node(var);
node.left = addAllRecur(c);
node.right = addAllRecur(c);
return node;
}
//之字形层次遍历(两个栈)
public void levelOrder() {
if (root == null) {
return;
}
LinkedList<Node> s1 = new LinkedList<Node>();//奇数行
LinkedList<Node> s2 = new LinkedList<Node>();//偶数行
//第几层
int levelNum = 1;
Node current;
s1.addFirst(root);
while (!s1.isEmpty() || !s2.isEmpty()) {
//当前行是奇数行
if (levelNum % 2 != 0) {
while (!s1.isEmpty()) {
current = s1.removeFirst();
System.out.print(current.data + " ");
if (current.left != null)
s2.addFirst(current.left);
if (current.right != null)
s2.addFirst(current.right);
}
levelNum++;
System.out.println();
}
//当前行是偶数行
else {
while (!s2.isEmpty()) {
current = s2.removeFirst();
System.out.print(current.data + " ");
if (current.right != null)
s1.addFirst(current.right);
if (current.left != null)
s1.addFirst(current.left);
}
levelNum++;
System.out.println();
}
}
}
private static class Node {
Integer data;
Node right;
Node left;
Node(Integer data) {
this.data = data;
}
}
}
测试类:
public class Demo {
public static void main(String[] args) {
//前序遍历建树
Integer[] arr = { 8, 6, 5, null, null, 7, null, null, 10, 9, null, null, 11, null, null };
BinaryTree tree = new BinaryTree(arr);
System.out.println("之字形层次遍历:");
tree.levelOrder();
}
}
建立的树:
测试结果:
之字形层次遍历:
8
10 6
5 7 9 11