package leetcode; public class Tree { private Integer[] treeArr; private int treeDep; private int wordLen = 1; private int gap = 3; // gap >= 3 public Tree(){ this(3); } public Tree(int wordLen) { this.wordLen = wordLen; if (wordLen % 2 == 0) throw new RuntimeException("word length must be single number!"); } /** * 根据传入数组生成节点树 * * @param arr * @return */ public TreeNode generator(Integer[] arr) { if ((arr.length - 1) % 2 != 0) { System.out.println("is not a valid tree array!!!"); return null; } TreeNode res = new TreeNode(arr[0], branch(1, arr), branch(2, arr)); return res; } private TreeNode branch(int index, Integer[] arr) { if (index >= arr.length || arr[index] == null) return null; TreeNode left = index * 2 + 1 < arr.length ? branch(index * 2 + 1, arr) : null; TreeNode right = index * 2 + 2 < arr.length ? branch(index * 2 + 2, arr) : null; TreeNode res = new TreeNode(arr[index], left, right); return res; } /** * 打印节点树 * * @param root */ public void print(TreeNode root) { printHelper(root); } /** * 打印节点树数组 * * @param root */ public void print(Integer[] root) { printHelper(generator(root)); } private void printHelper(TreeNode root) { treeDep = depth(root); treeArr = toArray(root); Integer[] last = slice(treeArr, treeArr.length - getLayerEleNum(treeDep), treeArr.length - 1); printLastLayer(last, treeDep); } private void output(String word) { int len = word.length(); int leftSpace = (wordLen - len) / 2; space(leftSpace); System.out.print(word); space(wordLen - len - leftSpace); } private void printLastLayer(Integer[] arr, int depth) { int cur = 0; for (int i = 0, len = arr.length; i < len; i++) { output(arr[i] == null ? "n" : arr[i] + ""); arr[i] = cur; cur += wordLen; if (i % 2 == 0) { space(gap); cur += gap; } else { System.out.print("|"); cur += 1; } } System.out.println(""); printLines(arr, depth); } private void printLines(Integer[] arr, int depth) { int cur = 0; //4 for (int i = 0, len = arr.length; i < len; i++) { int val; if (i % 2 == 0) { val = arr[i] + wordLen - cur; space(val); System.out.print("\\"); } else { val = arr[i] - cur - 1; space(val); System.out.print("/"); } cur += val + 1; arr[i] = cur; } System.out.println(""); printLayers(arr, depth - 1); } private void printLayers(Integer[] arr, int depth) { int curNum = getLayerEleNum(depth); int start = getLayerEleNumTotal(depth - 1); Integer[] ele = slice(treeArr, start, curNum + start - 1); int cur = 0; for (int i = 1, len = arr.length; i < len; i += 2) { int val = (arr[i - 1] + arr[i]) / 2 - wordLen / 2 - cur - 1; space(val); output(ele[i / 2] + ""); cur += val + wordLen; ele[i / 2] = cur - wordLen; } System.out.println(""); if(depth == 1)return; printLines(ele, depth); } /** * 获取节点树的深度 * * @param tree 节点树的根节点 * @return 深度 */ public static int depth(TreeNode tree) { return getDep(tree, 0); } private static int getDep(TreeNode tree, int layer) { if (tree == null) return layer; return Math.max(getDep(tree.left, layer + 1), getDep(tree.right, layer + 1)); } /** * 将节点数转换成数组 * * @param root 节点树的根节点 * @return 节点数组 */ public static Integer[] toArray(TreeNode root) { int dep = depth(root); Integer[] res = new Integer[getLayerEleNumTotal(dep)]; put(res, 0, root); return res; } /** * 将数组中对应元素放入节点树对应的位置 */ private static void put(Integer[] arr, int index, TreeNode node) { if (index >= arr.length) return; if (node == null) { arr[index] = null; return; } arr[index] = node.val; put(arr, index * 2 + 1, node.left); put(arr, index * 2 + 2, node.right); } /** * 打印节点树数组 * * @param tree 根节点 */ public static void printTreeArr(Integer[] tree) { System.out.println(""); for (int i = 0, len = tree.length; i < len; i++) { System.out.print(tree[i] + " "); } System.out.println(""); } /** * 获取从上到下所有层的元素数量之和 * * @param len 深度 * @return 所有元素数量 */ private static int getLayerEleNumTotal(int len) { int total = 0; for (int i = 0; i < len; i++) total += Math.pow(2,i); return total; } /** * 获取传入层的元素数量 * * @param index 深度 * @return 当前深度的元素数量 */ private static int getLayerEleNum(int index) { index -= 1; if (index <= 0) return 1; return (int) Math.pow(2, index); } private static void space(int num) { while (num-- > 0) System.out.print(" "); } /** * 从数组中切去[start,end]个元素并返回,包括start,end * * @param arr * @param start * @param end * @return */ private static Integer[] slice(Integer[] arr, int start, int end) { int len = end - start + 1; Integer[] ts = new Integer[len]; int offset = 0; while (offset < len) { ts[offset] = arr[offset + start]; offset++; } return ts; } /** * 验证树数组的长度是否符合,如果不符合要求则返回一个填充过符合长度要求的数组 * * @param treeLen * @return */ public static Integer[] verifyTreeArr(Integer[] treeArr) { int total = 0; int len = treeArr.length; int index = 0; while (total < len) total += Math.pow(2, index++); if (len < total) { Integer[] res = new Integer[total]; for (int i = 0, newLen = treeArr.length; i < newLen; i++) res[i] = treeArr[i]; return res; } return treeArr; } }