代码如下
import java.util.*; class TreeNode { int val; TreeNode left; TreeNode right; public TreeNode(int val) { this.val = val; } } public class Main { static Map<Integer, TreeNode> cache = new HashMap<>(); public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while(scanner.hasNext()) { int nodeNum = scanner.nextInt(); int rootNo = scanner.nextInt(); int n = nodeNum; int[][] info = new int[nodeNum][3]; int i = 0; while(n > 0) { info[i][0] = scanner.nextInt(); info[i][1] = scanner.nextInt(); info[i][2] = scanner.nextInt(); i++; n--; } TreeNode root = constructTree(rootNo, info); print(root); zigzagPrint(root); } } private static void print(TreeNode root) { if (root == null) { return; } System.out.print("Level 1 : "); Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); TreeNode last = root; TreeNode nLast = null; int level = 1; while(!queue.isEmpty()) { TreeNode head = queue.poll(); System.out.print(head.val + " "); if (head.left != null) { queue.offer(head.left); nLast = head.left; } if (head.right != null) { queue.offer(head.right); nLast = head.right; } if (last == head) { System.out.println(); level++; if (!queue.isEmpty()) { System.out.printf("Level %d : ", level); } last = nLast; } } } private static void zigzagPrint(TreeNode root) { if (root == null) { return; } Deque<TreeNode> deque = new LinkedList<>(); boolean orientation = true; int level = 1; deque.offer(root); TreeNode last = root; TreeNode nLast = null; System.out.print("Level 1 from left to right: "); while(!deque.isEmpty()) { TreeNode head = null; if (orientation) { head = deque.poll(); } else { head = deque.pollLast(); } System.out.print(head.val + " "); if (orientation) { if (head.left != null) { deque.offer(head.left); if (nLast == null) { nLast = head.left; } } if (head.right != null) { deque.offer(head.right); if (nLast == null) { nLast = head.right; } } } else { if (head.right != null) { deque.offerFirst(head.right); if (nLast == null) { nLast = head.right; } } if (head.left != null) { deque.offerFirst(head.left); if (nLast == null) { nLast = head.left; } } } if (last == head) { level++; last = nLast; System.out.println(); if (!deque.isEmpty()) { if (orientation) { System.out.printf("Level %d from right to left: ", level); } else { System.out.printf("Level %d from left to right: ", level); } orientation = !orientation; nLast = null; } } } } private static TreeNode constructTree(int rootNo,int [][] info) { for(int i = 0;i < info.length;i++) { int curNo = info[i][0]; TreeNode curNode = getOrCacheNode(curNo); int leftNo = info[i][1]; TreeNode leftNode = getOrCacheNode(leftNo); int rightNo = info[i][2]; TreeNode rightNode = getOrCacheNode(rightNo); curNode.left = leftNode; curNode.right = rightNode; } return getOrCacheNode(rootNo); } private static TreeNode getOrCacheNode(int no) { if (no == 0) { return null; } TreeNode exist = cache.get(no); if (exist == null) { exist = new TreeNode(no); cache.put(no, exist); } return exist; } }
把输入的数字存入info二维数组,constructTree方法用于构造树并返回树的根。
首先介绍按层打印的方法。
首先做判空处理,如果根空那么直接返回,什么都不打印。
如果根不空,把根入队,打印"Level 1 : ", 注意空格要与示例中相同。同时初始化层数level为1,并定义两个指针,last指向当前层最后一个元素,初始化是树根,nLast指向下一层的最后一个元素,因为现在暂且不知道,所以指向空即可。
当队列非空时循环处理,把队首元素拉出记为head,打印head的值,如果head左孩子不空,把head左孩子入队,nLast指向head左孩子,如果head右孩子不空,把head右孩子入队,nLast执行head右孩子。判断取出的元素是否已经是当前行最后一个,如果是,那么把层级数level加1,打印换行,之后再打印"Level 下一行号",并把当前行最后一个元素指针last指向nLast,nLast指向null或者保持不变均可。这里有一个小坑,如果已经扫到当前行最后一个元素且队列已经空了,那么是不应该再进入下一行并打印Level的,所以打印前要先判断队列非空。
接下来介绍zigzag打印的方法。
有了顺序打印的基础,zigzag只需要把队列变为双端队列,定义一个orientation的boolean类型变量表示当前行是从左到右还是从右到左,之后根据这个左右顺序不同来操作nLast指针移动和入队方式即可。
定义orientation为true表示当前行为从左向右。先做root判空,如果非空那么尾插(尾部插入,offer()或者offerLast())入队。首先直接打印"Level 1 from left to right: ",如果队列非空执行循环,如果检测到当前行方向是从左到右,那么就头弹(头部弹出,poll()或者pollFirst())记为head,否则尾弹(尾部弹出,pollLast())同样记为head,打印head对应的值。如果从左到右,那么就先取左孩子,再取右孩子;如果从右到左,就先取右孩子,再取左孩子。再从左到右取的过程中,均采用尾插。且只有nLast非空时才做赋值。如果是从右到左的过程,那么均采用头插法,nLast指针同样只有空时才做赋值。检测到当前节点是当前层的左后一个时,根据方向分别打印不同的串,把层级加一并改变方向,注意nLast一定要置空,否则在循环里就不动了。