算法基础部分-二叉树

public class Btree {
    public static class Node {
        public int value;
        public Node left;
        public Node right;
        public Node parent;

        public Node(int value) {
            this.value = value;
        }
    }

    //    遍历二叉树的三种顺序 先序是 中左右  中序是左中右  后序是左右中
//    先序遍历
    public static void xianxu(Node head) {
        if (head == null) {
            return;
        }
        System.out.print(head.value);
        xianxu(head.left);
        System.out.print(head.value);
        xianxu(head.right);
        System.out.print(head.value);
    }

    //    中序遍历
    public static void zhoxu(Node head) {
        if (head == null) {
            return;
        }
        zhoxu(head.left);
        System.out.print(head.value);
        zhoxu(head.right);
    }

    //    后序遍历
    public static void houxu(Node head) {
        if (head == null) {
            return;
        }
        houxu(head.left);
        houxu(head.right);
        System.out.print(head.value);
    }

    //    非递归实现先序 一个栈 先加入头 然后讲头的右边先加入栈然后再是左边
//    这样出来的时候就是从左到右了 ,并且每次弹出来的就从右到左判断是否有子节点如果有就按入栈
//
    public static void preOrderUnRecur(Node head) {
        System.out.println("pre-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            stack.add(head);
            while (!stack.isEmpty()) {
                head = stack.pop();
                //先打印
                System.out.print(head.value + " ");
//                然后先加入右
                if (head.right != null) {
                    stack.push(head.right);
                }
//                再加入左
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
        }
        System.out.println();
    }

    //    非递归实现后序
//    实现后续需要两个栈,第一个栈首先按从左到右按入栈
//    然后第二个栈就接收第一个栈弹出的元素
    //思维就是 首先栈是先进后出的因此是倒叙 所以我们要确定第二个栈加入元素的顺序是后序的倒叙 后序是左右中 那么加入的时候就得中右左
    public static void posOrderUnRecurl(Node head) {
        System.out.println("pos-order: ");
        if (head != null) {
            Stack<Node> s1 = new Stack<>();
            Stack<Node> s2 = new Stack<>();
            s1.push(head);
            while (!s1.isEmpty()) {
                head = s1.pop();
                s2.push(head);
                if (head.left != null) {
                    s1.push(head.left);
                }
                if (head.right != null) {
                    s1.push(head.right);
                }
            }
            while (!s2.isEmpty()) {
                System.out.print(s2.pop().value + " ");
            }
        }
        System.out.println();
    }

    //    非递归中序遍历 中序就是首先不断的加入左边的元素,然后左边没有了就弹出然后找右边
    public static void inOrderUnRecur(Node head) {
        System.out.println("in-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                } else {
                    head = stack.pop();
                    System.out.print(head.value + " ");
                    head = head.right;
                }
            }
        }
        System.out.println();
    }

    /*非递归实现先序*/
    public static void wxianxu(Node head) {
        //首先定义一个栈
        Stack<Node> stack = new Stack<>();
//        加入第一个元素
        stack.push(head);
        //如果栈中还有元素则循环
        while (stack.size() > 0) {
            head = stack.pop();
            System.out.print(head.value);
            if (head.right != null) {
                stack.push(head.right);
            }
            if (head.left != null) {
                stack.push(head.left);
            }
        }

    }

    public static void wzhoxu(Node head) {
        //中序首先也是定义一个栈
        Stack<Node> stack = new Stack<>();
        while (stack.size() > 0 || head != null) {
            if (head != null) {
                stack.push(head);
                head = head.left;
            } else {
                head = stack.pop();
                System.out.print(head.value);
                head = head.right;
            }
        }
    }

    //后序遍历
    public static void whouxu(Node head) {
//        定义两个栈
        Stack<Node> stack1 = new Stack<>();
        Stack<Node> stack2 = new Stack<>();
        stack1.push(head);
        while (stack1.size() > 0) {
            head = stack1.pop();
            stack2.push(head);
            if (head.left != null) {
                stack1.push(head.left);
            }
            if (head.right != null) {
                stack1.push(head.right);
            }
        }
        while (stack2.size() > 0) {
            System.out.print(stack2.pop().value);
        }
    }

    private static int preval = Integer.MIN_VALUE;

    //如何判断一个node 是不是搜索二叉树 (左节点<中点<右节点)
    public static boolean checkBST(Node head) {
        if (head == null) {
            return true;
        }
        boolean isbst = checkBST(head.left);
        if (!isbst) {
            return false;
        }
        if (head.value <= preval) {
            return false;
        } else {
            preval = head.value;
        }
        return checkBST(head.right);
    }

    public static boolean checkBST3(Node head) {
        if (head != null) {
            int prevalue = Integer.MIN_VALUE;
            Stack<Node> stack = new Stack<>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                } else {
                    head = stack.pop();
                    if (head.value <= prevalue) {
                        return false;
                    } else {
                        prevalue = head.value;
                    }
                    head = head.right;
                }
            }

        }
        return true;
    }

    public static class ReturnData {
        public int max;
        public int min;
        public boolean isBST;

        public ReturnData(int max, int min, boolean isBST) {
            this.max = max;
            this.min = min;
            this.isBST = isBST;
        }
    }

    //    如何判断一个node 是不是搜索二叉树 (套路法)
    public static ReturnData process(Node x) {
//        首先如果x=null就返回null
        if (x == null) {
            return null;
        }
//     首先得到左边的
        ReturnData leftData = process(x.left);
        //然后得到右边的
        ReturnData rightData = process(x.right);
        //然后定义最大值和最小值 一开始都等于x的值
        int min = x.value;
        int max = x.value;
        //然后进行左边的最小值和右边的最小值以及x的值进行比较得到最小值
        //左边的最大值和右边的最大值和x的值进行比较得到最大值
        if (leftData != null) {
            min = Math.min(min, leftData.min);
            max = Math.max(max, leftData.max);
        }
        if (rightData != null) {
            min = Math.min(min, rightData.min);
            max = Math.max(max, rightData.max);
        }
        boolean isbst = true;
        //现在得到的就是比较出来的最小值和最大值 然后就要判断是否符合搜索二叉树的条件
        //如果左边的树不为null 并且
        if (leftData != null && (!leftData.isBST || leftData.max >= x.value)) {
            isbst = false;
        }
        if (rightData != null && (!rightData.isBST || rightData.min <= x.value)) {
            isbst = false;
        }
        return new ReturnData(max, min, isbst);
    }

    //如何判断一个node是不是完全二叉树
    public static boolean isCBT(Node head) {
        if (head == null) {
            return true;
        }
        LinkedList<Node> queue = new LinkedList<>();
        //是否遇到过左右两个孩子不双全的节点
        boolean leaf = false;
        Node l = null;
        Node r = null;
        queue.add(head);
        while (!queue.isEmpty()) {
            head = queue.poll();
            l = head.left;
            r = head.right;
            if ((leaf && (l != null || r != null)) || (l == null && r != null)) {
                return false;
            }
            if (l != null) {
                queue.add(l);
            }
            if (r != null) {
                queue.add(r);
            }
            if (l == null || r == null) {
                leaf = true;
            }
        }
        return true;
    }

    //判断一个node是不是完全二叉树 (套路法)
    public static boolean isf(Node head) {
        Info data = f(head);
        return data.nodes == (1 << data.height) - 1;
    }

    public static class Info {
        //节点个数
        public int nodes;
        //高度
        public int height;

        public Info(int n, int h) {
            nodes = n;
            height = h;
        }
    }

    public static Info f(Node head) {
        if (head == null) {
            return new Info(0, 0);
        }
        Info leftInfo = f(head.left);
        Info rightInfo = f(head.right);
        //节点数等于左节点的数量和右节点的数量 +1相当加head自己
        int nodes = leftInfo.nodes + rightInfo.nodes + 1;
        //高度等于左边高度和右边高度较大数+1
        int height = Math.max(leftInfo.height, rightInfo.height) + 1;
        return new Info(nodes, height);
    }

    //返回两个点的最低公共祖先,两个节点往上然后汇聚的点就是最低公共祖先
    public static Node ancestor(Node head, Node o1, Node o2) {
//        首先如果当前head 为null 或者o1 或者o2 就直接返回
        if (head == null || head == o1 || head == o2) {
            return head;
        }
        Node left = ancestor(head.left, o1, o2);
        Node right = ancestor(head.right, o1, o2);
        if (left != null && right != null) {
            return head;
        }
        return left != null && right == null ? left : right;
    }

    //给你二叉树中的某个节点,返回该节点的后继节点
    public static Node getlast(Node head) {
        if (head == null) {
            return head;
        }
        //如果这个节点有右子树
        if (head.right != null) {
            return getleft(head.right);
            //当当前节点无右孩子节点时候就要看当前节点是不是父节点的左孩子
            // 如果不是就继续往上直到当前节点是父节点的左孩子然后返回父节点
        } else {
            Node parent = head.parent;
            while (parent.left != head && parent != null) {
                head = parent;
                parent = head.parent;
            }

            return parent;
        }
    }

    //
    public static Node getleft(Node head) {
        if (head == null) {
            return head;
        }
        while (head.left != null) {
            head = head.left;
        }
        return head;
    }

    //序列化二叉树
    public static void xuliehua(Node head) {
        Queue<Node> queue = new LinkedList<>();
        Stack<Node> stack = new Stack<>();
        if (head != null) {
            stack.push(head);
            while (stack.size() > 0) {
                head = stack.pop();
                queue.add(head);
                if (head != null) {
                    if (head.right != null) {
                        stack.push(head.right);
                    } else {
                        stack.push(null);
                    }
                    if (head.left != null) {
                        stack.push(head.left);
                    } else {
                        stack.push(null);
                    }
                }
            }
            StringBuffer sb = new StringBuffer("");
            while (queue.size() > 0) {
                Node node = queue.poll();
                if (node == null) {
                    sb.append("#_");
                } else {
                    sb.append(node.value + "_");
                }
            }
            System.out.println(sb.toString());
        }

    }

    //反序列化
    public static void fanxuliehua(String xulie) {
        String[] nodes = xulie.split("_");
        Queue<String> queue = new LinkedList<>();
        for (String s : nodes) {
            queue.add(s);
        }
        Node head = getnode(queue);

    }

    public static Node getnode(Queue<String> queue) {
        String poll = queue.poll();
        if (poll.equals("#")) {
            return null;
        }
        Node head = new Node(Integer.valueOf(poll));
        head.left = getnode(queue);
        head.right = getnode(queue);
        return head;
    }

    /*
    * 请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕
后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从
纸条的下边向,上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到
下依次是下折痕、下折痕和上折痕。
给定一个输入参数N,代表纸条都从下边向上方连续对折N次。请从上到下打
印所有折痕的方向。
*/
    public static void zhezhi(int n, int N, boolean b) {
//        如果当前的层数大于
        if (n > N) {
            return;
        }
        zhezhi(n + 1, N, true);
        System.out.println(b ? "凹" : "凸");
        zhezhi(n + 1, N, false);
    }

    public static void main(String[] args) {
//        Node head = new Node(7);
//        head.parent=null;
//        Node n1 = new Node(5);
//        n1.parent = head;
//        Node n2 = new Node(9);
//        n2.parent = head;
//        Node n3 = new Node(4);
//        n3.parent = n1;
//        Node n4 = new Node(6);
//        n4.parent = n1;
//        Node n5 = new Node(8);
//        n5.parent = n2;
//        head.left = n1;
//        head.right = n2;
//        n1.left = n3;
//        n1.right = n4;
//        n2.left = n5;
//        printTree(head);
//        isf(head);
        zhezhi(1,1,true);;

        Node n1 = new Node(1);
        Node n2 = new Node(2);
        Node n3 = new Node(3);
        Node n4 = new Node(4);
        Node n5 = new Node(5);
        Node n6 = new Node(6);
        Node n7 = new Node(7);
        Node n8 = new Node(8);
        n1.left = n2;
        n1.right = n3;
        n2.left = n4;
        n2.right = n5;
        n3.left = n6;
        n3.right = n7;
        n4.left = n8;
        printTree(n1);
        xianxu(n1);
    }

    //    打印二叉树的样子
    public static void printTree(Node head) {
        System.out.println("Binary Tree:");
        printInOrder(head, 0, "H", 17);
        System.out.println();

    }

    public static void printInOrder(Node head, int height, String to, int len) {
        if (head == null) {
            return;
        }
        printInOrder(head.right, height + 1, "v", len);
        String val = to + head.value + to;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(head.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值