题目一:不分行从上到下打印二叉树
解题思路:这其实就是二叉树的层次遍历,树的其他几种遍历方式容易用递归或者借助栈结构实现遍历。分析层次遍历的顺序,不难发现这儿可以借助一个队列作为辅助容器实现层次遍历。具体代码如下:
// 层次遍历打印二叉树
public ArrayList printFromTopToButtom(TreeNode root) {
ArrayList list = new ArrayList<>();
// 层次遍历树和图都需要一个队列,这儿用一个ArrayList实现 queue的数据逻辑
// 用LinkedList更好,它实现了Queue接口 可以调用 队列的 add offer element peek poll等方法
// 并且基本都是添加删除操作,效率会好一些
ArrayList queue = new ArrayList<>();
if (root == null)
return null;
queue.add(root);
while (queue.size() != 0) {
TreeNode tmp = queue.remove(0);
if (tmp.left != null) {
queue.add(tmp.left);
}
if (tmp.right != null) {
queue.add(tmp.right);
}
list.add(tmp.val);
}
return list;
}
题目二:分行从上到下打印二叉树
解题思路:主题和题目一相同,这里多了一步,我们需要判断树的每一行如何区分。代码中用了两个int变量分别记录当前行未打印节点个数以及下一行需要打印的个数来实现这个逻辑。
public void printTreeSplitRow(TreeNode root) {
ArrayList queue = new ArrayList<>();
if (root == null)
return;
queue.add(root);
// 分别记录当前行未打印个数 以及下一行需要打印的个数
int nextLevel = 0, toBePrint = 1;
while (!queue.isEmpty()) {
TreeNode tmp = queue.get(0);
System.out.print(tmp.val + " ");
if (tmp.left != null) {
queue.add(tmp.left);
nextLevel++;
}
if (tmp.right != null) {
queue.add(tmp.right);
nextLevel++;
}
queue.remove(0);
toBePrint--;
if (toBePrint == 0) {
// 当前行打印完毕
System.out.println();
toBePrint = nextLevel;
nextLevel = 0;
}
}
}
题目三:之字形打印二叉树
解题思路:分析之字形的顺序,可以发现节点是一个后进先出的顺序,我们需要两个辅助栈实现各行反序的逻辑。具体见代码注释
// 之字形打印二叉树 各行 从左往右 从右往左 交替打印
public void printTree(TreeNode root) {
if (root == null)
return;
// 按照这个要求我们需要两个栈辅助
// 交替使用两个栈 奇数层数据存放在stack1 偶数层在stack2
// 奇数层我们把下一层数据先left后right压入stack2 偶数层把下一层先right后left压入stack1
// 这样就可以实现隔层之字形打印
ArrayList stack1 = new ArrayList<>();
ArrayList stack2 = new ArrayList<>();
// 用一个flag标记 当前是奇数层还是偶数层
boolean flag = true;
TreeNode tmp = null;
stack1.add(root);
while (!stack1.isEmpty() || !stack2.isEmpty()) {
if (flag) {
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 + " ");
if (flag) {
if (tmp.left != null) {
stack2.add(tmp.left);
}
if (tmp.right != null) {
stack2.add(tmp.right);
}
} else {
if (tmp.right != null) {
stack1.add(tmp.right);
}
if (tmp.left != null) {
stack1.add(tmp.left);
}
}
// 当前层打印完毕 换行 并更改flag的值
if (flag) {
if (stack1.isEmpty()) {
System.out.println();
flag = !flag;
}
} else {
if (stack2.isEmpty()) {
System.out.println();
flag = !flag;
}
}
}
测试代码及结果:
public static void main(String[] args) {
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
TreeNode node5 = new TreeNode(5);
node1.left = node2;
node1.right = node3;
node2.left = node4;
node2.right = node5;
Problem32 p = new Problem32();
ArrayList list = p.printFromTopToButtom(node1);
for (Integer i : list) {
System.out.print(i + " ");
}
System.out.println();
p.printTreeSplitRow(node1);
p.printTree(node1);
}1 2 3 4 5
1
2 3
4 5
1
3 2
4 5