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;
    }
}

 

 posted on 2023-06-29 17:28  laremehpe  阅读(6)  评论(0编辑  收藏  举报