163 打印二叉树的边界节点
Table of Contents

ac

给定一颗二叉树的根节点 root,按照如下两种标准分别实现二叉树的边界节点的逆时针打印。
标准一:
1,根节点为边界节点。
2,叶节点为边界节点。
3,如果节点在其所在的层中是最左的或最右的,那么该节点也是边界节点。
标准二:
1,根节点为边界节点。
2,叶节点为边界节点。
3,树左边界延伸下去的路径为边界节点。
4,树右边界延伸下去的路径为边界节点。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

class TreeNode{
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode(int val) {
        this.val = val;
        left = null;
        right = null;
    }
}

public class Main {
    public static Scanner sc = new Scanner(System.in);

    public static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    public static long mod = (long)Math.pow(2,29);

    static Map<Integer, Integer> leftArr = new HashMap<>();
    static Map<Integer, Integer> rightArr = new HashMap<>();

    // 递归建立树
    static TreeNode buildTree(TreeNode root, int val){
        if(root == null){
            root = new TreeNode(val);
        }
        int left = leftArr.get(val);
        int right = rightArr.get(val);
        if(left != 0){
            root.left = buildTree(root.left, left);
        }
        if(right != 0){
            root.right = buildTree(root.right, right);
        }
        return root;
    }

    static int getHeight(TreeNode root){
        if(root == null){
            return 0;
        }
        return 1 + Math.max(getHeight(root.left), getHeight(root.right));
    }

    public static void main(String[] args) throws Exception{
        String line;
        String[] strArr;
        line = reader.readLine();
        strArr = line.split(" ");
        int n = Integer.valueOf(strArr[0]);
        int rootVal = Integer.valueOf(strArr[1]);
        for (int i = 0; i < n; i++) {
            line = reader.readLine();
            strArr = line.split(" ");
            int curVal = Integer.valueOf(strArr[0]);
            int leftVal = Integer.valueOf(strArr[1]);
            int rightVal = Integer.valueOf(strArr[2]);
            leftArr.put(curVal,leftVal);
            rightArr.put(curVal, rightVal);
        }
        TreeNode root = null;
        root = buildTree(root, rootVal);
        printEdge1(root);
        printEdge2(root);
    }


    static void printEdge2(TreeNode root){
        if(root == null){
            return;
        }
        System.out.print(root.val + " ");
        if(root.left != null && root.right != null){
            printLeftEdge(root.left,true);
            printRightEdge(root.right,true);
        }else {
            printEdge2(root.left != null ? root.left : root.right);
        }
        System.out.println();
    }

    // 从上往下打印左边界,包括的处理了最后一层
    static void printLeftEdge(TreeNode root, boolean print){
        if(root == null){
            return;
        }
        // 先打印根
        if(print || (root.left == null && root.right == null)){
            System.out.print(root.val + " ");
        }
        printLeftEdge(root.left, print);
        // 只有当左节点为null的时候才打印右节点
        printLeftEdge(root.right, print && root.left == null ? true : false);
    }

    // 从下往上打印右边界,包括的处理了最后一层
    static void printRightEdge(TreeNode root, boolean print){
        if(root == null){
            return;
        }
        printRightEdge(root.left, print && root.right == null ? true : false);
        printRightEdge(root.right, print);
        if(print || (root.left == null && root.right == null)){
            System.out.print(root.val + " ");
        }
    }

    static void printEdge1(TreeNode root){
        int height = getHeight(root);
        TreeNode[] leftEdge = new TreeNode[height + 1];
        TreeNode[] rightEdge = new TreeNode[height + 1];
        // 叶子节点
        List<TreeNode> leafList = new ArrayList<>();
        // 左侧的
        Queue<TreeNode> queue = new LinkedList<>();
        Queue<Integer> queueC = new LinkedList<>();
        queue.offer(root);
        queueC.offer(1);
        while (!queue.isEmpty()){
            TreeNode node = queue.poll();
            int ceng = queueC.poll();
            if(leftEdge[ceng] == null) {
                leftEdge[ceng] = node;
            }
            if(node.left != null){
                queue.offer(node.left);
                queueC.offer(ceng + 1);
            }
            if(node.right != null){
                queue.offer(node.right);
                queueC.offer(ceng + 1);
            }
        }
        // 右侧的
        queue.offer(root);
        queueC.offer(1);
        while (!queue.isEmpty()){
            TreeNode node = queue.poll();
            int ceng = queueC.poll();
            if(rightEdge[ceng] == null) {
                rightEdge[ceng] = node;
            }
            // 先右边再左边
            if(node.right != null){
                queue.offer(node.right);
                queueC.offer(ceng + 1);
            }
            if(node.left != null){
                queue.offer(node.left);
                queueC.offer(ceng + 1);
            }
        }
        // 非左,非右,且是叶子节点,按照每一层打印的
//        queue.offer(root);
//        queueC.offer(1);
//        while (!queue.isEmpty()){
//            TreeNode node = queue.poll();
//            int ceng = queueC.poll();
//            if(node.left == null && node.right == null && node != leftEdge[ceng] && node != rightEdge[ceng]) {
//                    leafList.add(node);
//            }
//            if(node.left !=  null){
//                queue.offer(node.left);
//                queueC.offer(ceng + 1);
//            }
//            if(node.right != null){
//                queue.offer(node.right);
//                queueC.offer(ceng + 1);
//            }
//        }
        leafList = getLeafList(root, height,1,leftEdge,rightEdge);
        // 一次打印即可
        // 左
        StringBuilder sb = new StringBuilder();
        for(int i=1;i<=height;i++){
            sb.append(leftEdge[i].val + " ");
        }
        // 叶子
        for(TreeNode node: leafList){
            sb.append(node.val + " ");
        }
        // 右
        for(int i=height;i>=1;i--){
            // 一层可能只有一个节点,左边打印了,则右边不需要打印了
            if(rightEdge[i] != leftEdge[i]) {
                sb.append(rightEdge[i].val + " ");
            }
        }
        String s = sb.toString();
        s = s.substring(0, s.length() - 1);
        System.out.println(s);
        return;
    }

    // 递归深度
    static List<TreeNode> getLeafList(TreeNode root, int height, int curCeng,
                                      TreeNode[] leftEdge,  TreeNode[] rightEdge){
        List<TreeNode> treeNodes = new ArrayList<>();
        if(root == null){
            return treeNodes;
        }
        if(root.left == null && root.right == null && root != leftEdge[curCeng] && root != rightEdge[curCeng]) {
            treeNodes.add(root);
        }
        treeNodes.addAll(getLeafList(root.left, height, curCeng + 1, leftEdge, rightEdge));
        treeNodes.addAll(getLeafList(root.right, height, curCeng + 1, leftEdge, rightEdge));
        return treeNodes;
    }
}
/*
         1
     /        \
  2              3
  \             /   \
  4            5     6
 / \          / \
7   8         9  10
     \       /
      11    12
     / \    / \
    13 14  15  16

16 1
1 2 3
2 0 4
4 7 8
7 0 0
8 0 11
11 13 14
13 0 0
14 0 0
3 5 6
5 9 10
10 0 0
9 12 0
12 15 16
15 0 0
16 0 0
6 0 0

1 2 4 7 11 13 14 15 16 12 10 6 3
1 2 4 7 13 14 15 16 10 6 3

44 44
44 18 10
18 22 1
22 40 0
40 0 34
34 36 0
36 31 0
31 0 0
1 41 9
41 30 27
30 0 19
19 0 0
27 16 0
16 32 0
32 0 0
9 3 39
3 0 12
12 0 0
39 20 11
20 4 0
4 0 0
11 0 0
10 38 2
38 7 0
7 23 35
23 0 8
8 42 0
42 0 0
35 0 28
28 0 0
2 14 21
14 6 0
6 24 0
24 15 43
15 0 0
43 0 5
5 33 0
33 26 0
26 0 0
21 17 25
17 29 13
29 0 0
13 0 0
25 0 37
37 0 0

44 18 22 40 34 36 31 5 33 26 19 32 12 4 11 42 28 15 29 13 43 37 25 21 2 10
44 18 22 40 34 36 31 19 32 12 4 11 42 28 15 26 29 13 37 25 21 2 10
*/