左程云 Java 笔记--二叉树


遍历

在这里插入图片描述

先序

递归法

    public static void preOrderRecur(Node head){
        if (head == null){
            return;
        }
        System.out.println(head.value + " ");
        preOrderRecur(head.left);
        preOrderRecur(head.right);
    }

非递归

在这里插入图片描述

public static void preOrderRecur1(Node head){
        if (head == null){
            return;
        }
        Stack<Node> stack = new Stack<>();
        stack.add(head);
        while (!stack.isEmpty()){
            head = stack.pop();
            System.out.println(head.value + " ");
            if (head.right != null){
                stack.push(head.right);
            }
            if (head.left != null){
                stack.push(head.right);
            }
        }
        System.out.println();
}

中序

递归法

public static void inOrderRecur(Node head){
        if (head == null){
            return;
        }
        inOrderRecur(head.left);
        System.out.println(head.value + " ");
        inOrderRecur(head.right);
    }

非递归

在这里插入图片描述

public static void inOrderRecur1(Node head){
        if (head == null){
            return;
        }
        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.println(head.value + " ");
                head = head.right
            }
        }
        System.out.println();
    }

后序

递归法

public static void posOrderRecur(Node head){
        if (head == null){
            return;
        }
        posOrderRecur(head.left);
        posOrderRecur(head.right);
        System.out.println(head.value + " ");
    }

非递归

头左右(入栈是 头右左)
(入栈头左右 再放入收集栈,遍历收集栈就是后序遍历)
在这里插入图片描述
(入栈头左右 再放入收集栈,遍历收集栈就是后序遍历)

public static void posOrderRecur1(Node head){
        if (head == null){
            return;
        }
        Stack<Node> stack = new Stack<>();
        Stack<Node> stack1 = new Stack<>();
        stack.add(head);
        while (! stack.isEmpty()){
            head = stack.pop();
            stack1.push(head);
            if (head.left != null){
                stack.push(head.left);
            }
            if (head.right != null){
                stack.push(head.right);
            }
        }
        while (stack1 != null){
            System.out.println(stack1.pop().value + " ");
        }
        System.out.println();
    }

深度优先遍历 == 先序遍历

宽度优先遍历

用队列,先进先出
先放头结点,弹出就打印,再放左再放右

public static void wOrder(Node head){
        if (head == null){
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        while (queue != null){
            Node cur = queue.poll();
            System.out.println(cur.value + " ");
            if (cur.left != null){
                queue.add(cur.left);
            }
            if (cur.right != null){
                queue.add(cur.right);
            }
        }
    }

求一棵二叉树最大宽度

在这里插入图片描述

    public static int wmax(Node head){
        if (head == null){
            return 0;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        HashMap<Node, Integer> map = new HashMap<>();
        map.put(head,1);
        int curLever = 1;
        int curLeverNodes = 0;
        int max = Integer.MIN_VALUE;
        while (queue != null){
            Node cur = queue.poll();
            int curNodeLevel = map.get(cur);
            if (curNodeLevel == curLever){
                curLeverNodes++;
            }else {
                max = Math.max(max,curLeverNodes);
                curLever++;
                curLeverNodes = 1;
            }
            System.out.println(cur.value + " ");
            if (cur.left != null){
                map.put(cur.left,curLever+1);
                queue.add(cur.left);
            }
            if (cur.right != null){
                map.put(cur.right,curLever+1);
                queue.add(cur.right);
            }
        }
        return max;
    }

二叉树的相关概念及其实现判断

如何判断一颗二叉树是否是搜索二叉树?

在这里插入图片描述
(每颗子树都是左树比右树小)

中序遍历,如果都是升序就是搜索二叉树

    public static boolean chackBST(Node head){
        int preValue = Integer.MIN_VALUE;
        if (head == null){
            return true;
        }
        boolean isLeftBST = chackBST(head.left);
        if (!isLeftBST){
            return false;
        }
        if (head.value <= preValue) {
            return false;
        } else {
            preValue = head.value;
        }
        return chackBST(head.right);
    }
    public static boolean checkBST2(Node head){
        int preValue = Integer.MIN_VALUE;
        if (head == null){
            return true;
        }
        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 boolean checkBST3(Node head){
        return process1(head).isBST;
    }
    public static class ReturnData{
        public boolean isBST;
        public int max;
        public int min;

        public ReturnData(boolean isBST, int max, int min) {
            this.isBST = isBST;
            this.max = max;
            this.min = min;
        }
    }
    public static ReturnData process1(Node x){
        if (x == null){
            return  null;
        }
        ReturnData leftData = process1(x.left);
        ReturnData rightData = process1(x.right);
        int min = x.value;
        int max = x.value;
        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;
        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(isBST,min,max);
    }

如何判断一颗二叉树是完全二叉树?

在这里插入图片描述

按宽度来遍历

  1. 有右无左 返回false
  2. 在1不违规的情况下,如果遇到了第一个左右不全的节点,则后面的都为叶节点。
    public static boolean isCBT(Node head){
        if (head == null){
            return true;
        }
        LinkedList<Node> queue = new LinkedList<>();
        boolean leaf = false;//是否遇到左右不双全的节点,无false,有就为ture
        Node l = null;
        Node r = null;
        queue.add(head);
        while (!queue.isEmpty()){
            head = queue.poll();
            l = head.left;
            r = head.right;
            if (//第一个是 不双全但还有子节点  第二个是 左无右有  直接false
                    (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
                leaf = true;
            }
        }
        return true;
    }

如何判断一颗二叉树是否是满二叉树?

  • 最大深度 L 节点数 N 如果满足 n = 2^L -1 就是满二叉树

套路解法

    public static boolean isF(Node head){
        if (head == null){
            return true;
        }
        Info data = process3(head);
        return data.nodes == (1 << data.height -1);
    }
    public static class Info{
        public int nodes;
        public int height;

        public Info(int nodes, int height) {
            this.nodes = nodes;
            this.height = height;
        }
    }
    public static Info process3(Node x){
        if (x == null){
            return new Info(0,0);
        }
        Info leftData = process3(x.left);
        Info rightData = process3(x.right);

        int height = Math.max(leftData.height, rightData.height)+1;
        int nodes = leftData.nodes + rightData.nodes +1;

        return new Info(height,nodes);
    }

如何判断一颗二叉树是否是平衡二叉树? (二叉树题目 套路)

在这里插入图片描述

套路解法

public static boolean isBalanced(Node head){
        return process(head).isBalanced;
    }
    public static class ReturnType{
        public boolean isBalanced;
        public int height;
        public ReturnType(boolean isBalanced, int height) {
            this.isBalanced = isBalanced;
            this.height = height;
        }
    }
    public static ReturnType process(Node x){
        if (x == null){
            return new ReturnType(true,0);
        }

        ReturnType leftData = process(x.left);
        ReturnType rightData = process(x.right);

        int height = Math.max(leftData.height, rightData.height)+1;
        boolean isBalanced = leftData.isBalanced && rightData.isBalanced
                && Math.abs(leftData.height- rightData.height) < 2;
        return new ReturnType(isBalanced,height);
    }

*递归套路 =====》树型DP*

最低公共祖先

    public static Node lca(Node head, Node o1, Node o2){
        HashMap<Node,Node> fathermap = new HashMap<>();
        fathermap.put(head,head);
        process4(head,fathermap);
        HashSet<Node> set1 = new HashSet<>();
        Node cur = o1;
        while (cur != fathermap.get(cur)){
            set1.add(cur);
            cur = fathermap.get(cur);
        }
        set1.add(head);

        Node cur2 = o2;
        while (!set1.contains(cur2)){
            cur2 = fathermap.get(cur2);
        }
        return cur2;
    }
    public static void process4(Node head, HashMap<Node, Node> fathermap) {
        if (head == null){
            return;
        }
        fathermap.put(head.left,head);
        fathermap.put(head.right,head);
        process4(head.left, fathermap);
        process4(head.right, fathermap);
    }
  1. o1是o2 / o2是o1 的最低公共祖先
  2. o1o2不互为公共祖先(向上汇聚找到)
    public static Node lowca(Node head, Node o1, Node o2){
        if (head == null || head == o1 || head == o2){
            return head;
        }
        Node left = lowca(head.left, o1, o2);
        Node right = lowca(head.right, o1, o2);
        if (left != null && right != null){
            return head;
        }
        return left != null ? left : right;
    }

在二叉树中找到一个节点的后继节点

[题目]现在有 - -种新的二叉树节点类型如下:

public class Node{
	public int value;
	public Node left;
	public Node right;
	public Node parent;
	public Node(int val) {
		value = val ;
	}
}

该结构比普通二叉树节点结构多了一个指向父节点的parent指针。
假设有一棵Node类型的节点组成的二叉树,树中每个节点的parent指针都正确地指向自己的父节点,头节点的parent指向null。
只给一个在二叉树中的某个节点node,请实现返回node的后继节点的函数。
(在二叉树的中序遍历的序列中,node的 下一个节点叫作node的后继节点。)

  1. x有右树,后继是右树的最左边
  2. x无右树,向上找,是一个节点的左树时这个节点是x的后继
  3. 向上一直不是左节点,则为最右的节点,后继为null
   public static Node1 getSuccessorNode(Node1 node){
        if (node == null){
            return node;
        }
        if (node.right != null){
            return getLeftMost(node.right);
        }else { //无右子树
            Node1 parent = node.parent;
            while (parent != null && parent.left != node){
                node = node.parent;
                parent = node.parent;
            }
            return parent;
        }
    }
    public static Node1 getLeftMost(Node1 node) {
        if (node == null){
            return node;
        }
        if (node.left != null){
            node = node.left;
        }
        return node;
    }

二叉树的序列化和反序列化

就是内存里的一棵树如何变成字符串形式,又如何从字符串形式变成内存里的树
在这里插入图片描述

    public static String serialByPre(Node head){
        if (head == null){
            return "#_";
        }
        String res = head.value + "_";
        res += serialByPre(head.left);
        res += serialByPre(head.right);
        return res;
    }
    public static Node reconByPreString(String preStr){
        String[] values = preStr.split("_");
        Queue<String> queue = new LinkedList<>();
        for (int i = 0; i < values.length; i++) {
            queue.add(values[i]);
        }
        return reconPreOrder(queue);
    }

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

如何判断一颗二叉树是不是另一棵二叉树的子树?

折纸问题

在这里插入图片描述

   public static void printAllFolds(int N){
        printProcess(1,N,true);
    }
    public static void printProcess(int i, int N, boolean down){
        if (i > N){
            return;
        }
        printProcess(i+1,N,true);
        System.out.println(down ? "凹" : "凸");
        printProcess(i+1,N,false);
    }

总结

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值