剑指Offer 面试题32:从上到下打印二叉树 Java代码实现

题目一:不分行从上到下打印二叉树

解题思路:这其实就是二叉树的层次遍历,树的其他几种遍历方式容易用递归或者借助栈结构实现遍历。分析层次遍历的顺序,不难发现这儿可以借助一个队列作为辅助容器实现层次遍历。具体代码如下:

// 层次遍历打印二叉树
	public ArrayList<Integer> printFromTopToButtom(TreeNode root) {
		ArrayList<Integer> list = new ArrayList<>();
		// 层次遍历树和图都需要一个队列,这儿用一个ArrayList实现 queue的数据逻辑
		// 用LinkedList更好,它实现了Queue接口 可以调用 队列的 add offer element peek poll等方法
		// 并且基本都是添加删除操作,效率会好一些
		ArrayList<TreeNode> 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<TreeNode> 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<TreeNode> stack1 = new ArrayList<>();
		ArrayList<TreeNode> 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<Integer> 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 

2 3 
4 5 

3 2 
4 5 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值