【算法数据结构体系篇class10、11】:二叉树

news2024/11/14 23:36:15

一、二叉树的先序、中序、后序遍历

先序:任何子树的处理顺序都是,先头节点、再左子树、然后右子树

中序:任何子树的处理顺序都是,先左子树、再头节点、然后右子树

后序:任何子树的处理顺序都是,先左子树、再右子树、然后头节点

二、递归方式实现二叉树的先序、中序、后序遍历

1)理解递归序
能回到节点处3次
2)先序、中序、后序都可以在递归序的基础上加工出来

3)第一次到达一个节点就打印就是先序、第二次打印即中序、第三次即后序

代码演示:

package class10;

/**
 * 递归方式:先序 中序 后序 打印二叉树
 */
public class RecursiveTraversalBT {
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int v) {
            value = v;
        }
    }

    //先序打印全部节点  根左右
    public static void pre(Node head) {
        if (head == null) return;
        System.out.println(head.value);
        pre(head.left);
        pre(head.right);
    }

    //中序打印全部节点  左根右
    public static void in(Node head) {
        if (head == null) return;
        in(head.left);
        System.out.println(head.value);
        in(head.right);
    }

    //后序打印全部节点 左右根
    public static void pos(Node head) {
        if (head == null) return;
        pos(head.left);
        pos(head.right);
        System.out.println(head.value);
    }

    public static void main(String[] args) {
        Node head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = new Node(4);
        head.left.right = new Node(5);
        head.right.left = new Node(6);
        head.right.right = new Node(7);

        pre(head);
        System.out.println("========");
        in(head);
        System.out.println("========");
        pos(head);
        System.out.println("========");
    }
}
"D:\Program Files\Java\jdk1.8.0_151\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\lib\idea_rt.jar=63444:D:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\bin" -Dfile.encoding=UTF-8 -classpath "D:\Program Files\Java\jdk1.8.0_151\jre\lib\charsets.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\deploy.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\access-bridge-64.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\cldrdata.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\dnsns.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jaccess.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jfxrt.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\localedata.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\nashorn.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunec.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunjce_provider.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunmscapi.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunpkcs11.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\zipfs.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\javaws.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jce.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jfr.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jfxswt.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jsse.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\management-agent.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\plugin.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\resources.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\rt.jar;D:\Java\algorithm\算法和数据结构体系学习班代码\算法和数据结构体系学习班代码\bin" class10.RecursiveTraversalBT
1
2
4
5
3
6
7
========
4
2
5
1
6
3
7
========
4
5
2
6
7
3
1
========

Process finished with exit code 0

三、X节点的祖先节点 交集

X节点的祖先节点 交集
先序遍历顺序在X之前的节点 ∩ 后序遍历顺序在X之后的节点

1.先序遍历是根左右,祖先节点都是在排在前面的后续遍历是左右根,祖先节点都是排在后面的 所以是两次遍历的交集节点。就是祖先节点
2.X的孩子节点不会出现在该交集中,先序遍历根左右 孩子节点是排在后面的 不在该交集
3.X作为左树,它的右兄弟节点不会出现该交集中。先序遍历根左右,右兄弟节点都是在后面,所以不会再该交集
4.X作为右树,它的左兄弟节点不会出现该交集中,后序遍历左右根,左兄弟节点都是再前面,所以不会在该交集
全部节点类型判断分析结束
至此,证明先序遍历顺序在X之前的节点 ∩ 后序遍历顺序在X之后的节点 两者交集的节点 就是X祖先节点

四、非递归方式实现二叉树的先序、中序、后序遍历

1)任何递归函数都可以改成非递归

2)自己设计压栈的来实现

代码演示:

package class10;

import java.util.Stack;


/**
 * 非递归方式:先序 中序 后序 打印二叉树
 */
public class UnRecursiveTraversalBT {
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int v) {
            value = v;
        }
    }

    //先序 利用栈结构,遍历入栈,先打印,在入右节点 再入左节点,这样出栈才是左在右前面
    public static void pre(Node head){
        System.out.print("pre-order: ");
        if(head != null){
            Stack<Node> stack = new Stack<>();
            //头节点先入栈
            stack.push(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();
    }


    //中序 先遍历左子树节点都入栈直到null,就弹出,再指向右子树,右子树再遍历完它的左子树入栈 再弹出
    public static void in(Node cur){
        System.out.print("in-order: ");
        if(cur != null){
            Stack<Node> stack = new Stack<>();
            while(!stack.isEmpty() || cur != null){
                //1.当前节点非空,节点入栈,并往左子树下沉,直到左子树为空
                if(cur != null){
                    stack.push(cur);
                    cur = cur.left;
                }else{
                    //左子树空,那么就弹出其前节点,然后再下沉右子树。
                    //循环去遍历右子树的子节点
                    cur = stack.pop();
                    System.out.print(cur.value + " ");
                    cur = cur.right;
                }
            }
        }
        System.out.println();
    }

    //后序 已知先序是根左右,那么可以先得到根右左,然后再逆序 变成左右根 需要两个栈
    public static void pos1(Node head){
        System.out.print("pos-order: ");
        if(head !=null){
            //建立两个栈,stack1出栈顺序为根右左,然后依次入栈stack2 出栈顺序就逆序变成左右根  中序遍历
            Stack<Node> stack1 = new Stack<>();
            Stack<Node> stack2 = new Stack<>();
            stack1.push(head);
            while(!stack1.isEmpty()){
                Node node = stack1.pop();
                stack2.push(node);
                if(node.left != null){
                    stack1.push(node.left);
                }
                if(node.right != null){
                    stack1.push(node.right);
                }
            }
            //入栈是 根右左  出栈就是左右根
            while (!stack2.isEmpty()){
                System.out.print(stack2.pop().value+" ");
            }
        }
        System.out.println();
    }

    //后序  只用一个栈
    public static void pos2(Node head){
        System.out.print("pos-order: ");
        if(head != null){
            Stack<Node> stack = new Stack<>();
            //栈先入头节点
            stack.push(head);
            //辅助变量cur 存放每次的栈顶节点
            Node cur = null;
            while(!stack.isEmpty()){
                //取出当前栈顶元素。
                cur = stack.peek();
                //判断栈顶元素左节点是否非空 是否左右节点不等于 弹出的上个节点head.
                if(cur.left!=null && cur.left != head && cur.right != head){
                    //符合则左子节点入栈
                    stack.push(cur.left);
                    //来到右节点判断 非空 且弹出的head节点不等于其右节点。
                }else if(cur.right != null && cur.right != head){
                    //符合则右节点入栈入栈
                    stack.push(cur.right);
                }else {
                    //如果左右子节点都为空 或者说head是其cur节点的子节点(这个说明是从下往上倒回去,下面的子节点已经遍历且抛出打印了 不能再入栈)
                    //那就再出栈顶元素,打印 且将head节点赋值为当前出栈的元素,用于上层的cur节点遍历比较
                    cur = stack.pop();
                    System.out.print(cur.value + " ");
                    head = cur;
                }
            }
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = new Node(4);
        head.left.right = new Node(5);
        head.right.left = new Node(6);
        head.right.right = new Node(7);

        pre(head);
        System.out.println("========");
        in(head);
        System.out.println("========");
        pos1(head);
        System.out.println("========");
        pos2(head);
        System.out.println("========");
    }
}
"D:\Program Files\Java\jdk1.8.0_151\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\lib\idea_rt.jar=63453:D:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\bin" -Dfile.encoding=UTF-8 -classpath "D:\Program Files\Java\jdk1.8.0_151\jre\lib\charsets.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\deploy.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\access-bridge-64.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\cldrdata.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\dnsns.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jaccess.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jfxrt.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\localedata.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\nashorn.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunec.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunjce_provider.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunmscapi.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunpkcs11.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\zipfs.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\javaws.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jce.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jfr.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jfxswt.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jsse.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\management-agent.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\plugin.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\resources.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\rt.jar;D:\Java\algorithm\算法和数据结构体系学习班代码\算法和数据结构体系学习班代码\bin" class10.UnRecursiveTraversalBT
pre-order: 1 2 4 5 3 6 7 
========
in-order: 4 2 5 1 6 3 7 
========
pos-order: 4 5 2 6 7 3 1 
========
pos-order: 4 5 2 6 7 3 1 
========

Process finished with exit code 0

五、实现二叉树的按层遍历

1)其实就是宽度优先遍历,用队列

2)可以通过设置flag变量的方式,来发现某一层的结束(看题目)

package class11;

import java.util.LinkedList;
import java.util.Queue;

/**
 * 层序遍历,从上往下 从左往右打印节点
 * 利用队列
 */
public class LevelTraversalBT {
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int v) {
            value = v;
        }
    }

    //层序遍历
    public static void level(Node head){
        if(head == null) return;
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        while(!queue.isEmpty()){
            head = queue.poll();
            System.out.println(head.value);
            if(head.left != null){
                queue.add(head.left);
            }
            if(head.right != null){
                queue.add(head.right);
            }
        }
    }

    public static void main(String[] args) {
        Node head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = new Node(4);
        head.left.right = new Node(5);
        head.right.left = new Node(6);
        head.right.right = new Node(7);

        level(head);
        System.out.println("========");
    }
}

六、实现二叉树的序列化和反序列化

1)先序方式序列化和反序列化

2)按层方式序列化和反序列化

/*
* 二叉树可以通过先序、后序或者按层遍历的方式序列化和反序列化,
* 以下代码全部实现了。
* 但是,二叉树无法通过中序遍历的方式实现序列化和反序列化
* 因为不同的两棵树,可能得到同样的中序序列,即便补了空位置也可能一样。
* 比如如下两棵树
* __2
* /
* 1
* 和
* 1__
* \
* 2
* 补足空位置的中序遍历结果都是{ null, 1, null, 2, null}
*
* */
package class11;


import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * 序列化:将二叉树结构序列化成字符串,这里用集合保存字符串
 * 表示将内存的数据结构给保存到硬盘中,长期保存 转换成字节或字符
 * 反序列化:将序列化后的字符集合反序列回 二叉树结构, 再恢复原结构到内存中
 */
public class SerializeAndReconstructTree {
    /*
     * 二叉树可以通过先序、后序或者按层遍历的方式序列化和反序列化,
     * 以下代码全部实现了。
     * 但是,二叉树无法通过中序遍历的方式实现序列化和反序列化
     * 因为不同的两棵树,可能得到同样的中序序列,即便补了空位置也可能一样。
     * 比如如下两棵树
     *         __2
     *        /
     *       1
     *       和
     *       1__
     *          \
     *           2
     * 补足空位置的中序遍历结果都是{ null, 1, null, 2, null}
     *
     * */
    public static class Node {
        public int value;
        public Node left;
        public Node right;

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

    //先序遍历方式实现序列化
    public static Queue<String> preSerial(Node head) {
        //定义字符串型队列保存每个二叉树节点
        Queue<String> ans = new LinkedList<>();
        //先序遍历
        pres(head, ans);
        return ans;
    }

    public static void pres(Node head, Queue<String> ans) {
        //为空,则添加null,空位置注意一定要填充位置,否则还原二叉树会有歧义的
        if (head == null) {
            ans.add(null);
        } else {
            //根左右
            ans.add(String.valueOf(head.value));
            pres(head.left, ans);
            pres(head.right, ans);

        }
    }

    //先序队列实现反序列化,构建二叉树
    public static Node buildByPreQueue(Queue<String> prelist) {
        //如果队列为空或者大小0  直接返回空节点
        if (prelist == null || prelist.size() == 0) {
            return null;
        }
        return preb(prelist);
    }

    //队列不为空 那么就进行反序列化 先序序列 构建二叉树
    private static Node preb(Queue<String> prelist) {
        //先弹出节点
        String value = prelist.poll();
        //null则表示空节点,返回null节点
        if (value == null) {
            return null;
        }
        //先序 根左右,先定义当前节点,在定义其左子树  右子树
        Node head = new Node(Integer.valueOf(value));
        head.left = preb(prelist);
        head.right = preb(prelist);
        //返回头节点
        return head;
    }

//    -----------------------------------------------------

    //后序遍历方式实现序列化
    public static Queue<String> posSerial(Node head) {
        Queue<String> ans = new LinkedList<>();
        poss(head, ans);
        return ans;
    }

    public static void poss(Node head, Queue<String> ans) {
        if (head == null) {
            ans.add(null);
        } else {
            poss(head.left, ans);
            poss(head.right, ans);
            ans.add(String.valueOf(head.value));
        }
    }

    //后序队列实现反序列化,构建二叉树
    public static Node buildByPosQueue(Queue<String> poslist) {
        if (poslist == null || poslist.size() == 0) {
            return null;
        }
        //后序遍历队列是 左右根,可以转换为 逆序保存在栈 出栈即,根右左。 便于构建二叉树能返回根节点
        Stack<String> stack = new Stack<>();
        while (!poslist.isEmpty()) {
            //队列入栈
            stack.push(poslist.poll());
        }
        return posb(stack);
    }

    //后序遍历队列顺序是 左右根
    public static Node posb(Stack<String> posstack) {
        String value = posstack.pop();
        if (value == null) {
            return null;
        }
        //注意,因为出栈顺序是 根右左,所以先定义根节点,然后在递归其右子树,再是左子树
        Node head = new Node(Integer.valueOf(value));
        head.right = posb(posstack);
        head.left = posb(posstack);
        return head;
    }

//    ----------------------------------------------------------

    //层序遍历方式实现序列化   需要额外一个队列辅助保存每层元素按序输出
    public static Queue<String> levelSerial(Node head) {
        Queue<String> ans = new LinkedList<>();
        if (head == null) {
            ans.add(null);
        } else {
            //头非空,结果集合入头节点  辅助队列也入头节点
            ans.add(String.valueOf(head.value));
            Queue<Node> queue = new LinkedList<>();
            queue.add(head);
            while (!queue.isEmpty()) {
                //辅助队列不为空,则弹出队首,依次遍历左右子节点,非空则再入辅助队列,入结果队列,为空则结果队列入null
                head = queue.poll();
                //左子节点非空,那么入结果队列 辅助队列
                if (head.left != null) {
                    ans.add(String.valueOf(head.left.value));
                    queue.add(head.left);
                } else {
                    //为空 则入结果队列null
                    ans.add(null);
                }
                if (head.right != null) {
                    ans.add(String.valueOf(head.right.value));
                    queue.add(head.right);
                } else {
                    ans.add(null);
                }
            }
        }
        return ans;
    }

    //层序队列实现反序列化,构建二叉树
    public static Node buildByLevelQueue(Queue<String> levelList) {
        if (levelList == null || levelList.size() == 0) {
            return null;
        }
        //定义一个节点队列,用于进行保存levelList的节点 先保存根节点,后续进行遍历
        Queue<Node> queue = new LinkedList<>();
        Node head = generateNode(levelList.poll());
        //注意判断可能节点是null [null]的情况 避免报空指针
        if (head != null) {
            queue.add(head);
        }
        //辅助节点用来遍历从head开始每一个节点
        Node node = null;
        while (!queue.isEmpty()) {
            //遍历一开始保存了头节点的辅助队列,弹出节点
            node = queue.poll();
            //依次弹出原层序队列节点,就是从上到下从左往右,然后分别构建头节点的左节点 右节点,
            node.left = generateNode(levelList.poll());
            node.right = generateNode(levelList.poll());
            //非空,那么就表示有左子树,左节点入队列,继续下一轮的遍历
            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
        //最后构建完之后返回head节点
        return head;
    }

    //构建节点函数,传入levelList层序队列字符串,为空则返回null节点,不为空则创建新节点返回
    public static Node generateNode(String val) {
        if (val == null) {
            return null;
        }
        return new Node(Integer.valueOf(val));
    }

    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    // for test
    public static boolean isSameValueStructure(Node head1, Node head2) {
        if (head1 == null && head2 != null) {
            return false;
        }
        if (head1 != null && head2 == null) {
            return false;
        }
        if (head1 == null && head2 == null) {
            return true;
        }
        if (head1.value != head2.value) {
            return false;
        }
        return isSameValueStructure(head1.left, head2.left) && isSameValueStructure(head1.right, head2.right);
    }

    // for test
    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();
    }

    public static void main(String[] args) {
        int maxLevel = 5;
        int maxValue = 100;
        int testTimes = 1000000;
        System.out.println("test begin");
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            Queue<String> pre = preSerial(head);
            Queue<String> pos = posSerial(head);
            Queue<String> level = levelSerial(head);
            Node preBuild = buildByPreQueue(pre);
            Node posBuild = buildByPosQueue(pos);
            Node levelBuild = buildByLevelQueue(level);
            if (!isSameValueStructure(preBuild, posBuild) || !isSameValueStructure(posBuild, levelBuild)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("test finish!");

    }


}

七、Leetcode431. Encode N-ary Tree to Binary Tree

/** 431leetcode
* // 本题测试链接: https://leetcode.com/problems/encode-n-ary-tree-to-binary-tree
* 多叉树转二叉树
* 思路:多叉树就是多个子节点,可以转换二叉树按照这个定义来转换:当前节点的子节点,就依次放到其左子树的右孩子节点
* 比如 0节点 123孩子节点 1节点 45孩子节点,2节点 678孩子节点,3节点 9孩子节点
* 0
* 1 2 3
* 4 5 6 7 8 9
*
* 转换二叉树如下:
* 0
* 1
* 4 2
* 5 6 3
* 7 9
* 8
*/
package class11;


import java.util.ArrayList;
import java.util.List;

/** 431leetcode
 * // 本题测试链接:https://leetcode.com/problems/encode-n-ary-tree-to-binary-tree
 * 多叉树转二叉树
 * 思路:多叉树就是多个子节点,可以转换二叉树按照这个定义来转换:当前节点的子节点,就依次放到其左子树的右孩子节点
 *       比如 0节点 123孩子节点 1节点 45孩子节点,2节点 678孩子节点,3节点 9孩子节点
 *       0
 *    1    2      3
 * 4  5   6 7 8    9
 *
 * 转换二叉树如下:
 *           0
 *       1
 *    4         2
 *      5   6         3
 *            7     9
 *              8
 */
public class EncodeNaryTreeToBinaryTree {
    // 提交时不要提交这个类
    public static class Node {
        public int val;
        public List<Node> children;

        public Node() {
        }

        public Node(int _val) {
            val = _val;
        }

        public Node(int _val, List<Node> _children) {
            val = _val;
            children = _children;
        }
    };

    // 提交时不要提交这个类
    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            val = x;
        }
    }

    class Codec {
        //多叉树转二叉树
        public TreeNode encode(Node root){
            if(root == null){
                return null;
            }
            //非空,当前多叉树的root节点为根节点,可先将其赋值给二叉树根节点
            TreeNode head = new TreeNode(root.val);
            //转换成二叉树,可以定义其多叉树的每个节点的孩子节点都转换成当前节点的左子树,并且依次放在左子树的右节点,形成一个右树形式
            head.left = en(root.children);
            return head;
        }
        public TreeNode en(List<Node> children){
            //定义两个辅助节点变量进行递归
            TreeNode head = null;
            TreeNode cur = null;
            for(Node child:children){
                //获取当前孩子节点的值,并创建对应的二叉树节点
                TreeNode tNode = new TreeNode(child.val);
                //头为空,比如第一次进入那么就将当前节点赋值head
                if(head == null){
                    head =tNode;
                }else{
                    //如果为空,说明已经遍历了第一个孩子节点 就将当前cur的右指针指向下个孩子节点。 即将同层的孩子节点都形成一个右树
                    cur.right = tNode;
                }
                //这里cur辅助变量 来表示当前遍历到哪个节点
                cur = tNode;
                //接着往左递归。看该节点是否有孩子节点 继续处理该节点的孩子节点 再递归回上层处理
                cur.left = en(child.children);
            }
            return head;
        }

        //二叉树转多叉树
        public Node decode(TreeNode root){
            if(root == null){
                return null;
            }
            //非空 创建一个多叉树,节点为当前二叉树根节点,孩子节点是根节点的左树,左树进行递归完善底层的结构
            return new Node(root.val,de(root.left));
        }
        public  List<Node> de(TreeNode root){
            //定义一个当前节点的孩子节点集合。来返回当前节点的孩子节点
            List<Node> children = new ArrayList<>();
            if(root != null){
                //当根节点不为空,继续往左子树创建多叉树的节点cur,表示每个树根节点的孩子节点
                Node cur = new Node(root.val,de(root.left));
                //加入集合,然后遍历的二叉树节点要往右沉,往右的是同层孩子节点,添加之前还会递归去处理右节点自己的子树
                children.add(cur);
                root = root.right;
            }
            //最后返回根的孩子节点。
            return children;
        }


    }

}

八、如何设计一个打印整棵树的打印函数

package class11;

/**
 * 打印二叉树
 *
 * H1H根节点 第一排
 * V1v 表示左边一排下方离我最近的跟我连接
 * ^1^ 表示左边一排上方理我最近的跟我连接
 */
public class Code04_PrintBinaryTree {

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

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

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

    public static void main(String[] args) {
        Node head = new Node(1);
        head.left = new Node(-222222222);
        head.right = new Node(3);
        head.left.left = new Node(Integer.MIN_VALUE);
        head.right.left = new Node(55555555);
        head.right.right = new Node(66);
        head.left.left.right = new Node(777);
        printTree(head);

        head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = new Node(4);
        head.right.left = new Node(5);
        head.right.right = new Node(6);
        head.left.left.right = new Node(7);
        printTree(head);

        head = new Node(1);
        head.left = new Node(1);
        head.right = new Node(1);
        head.left.left = new Node(1);
        head.right.left = new Node(1);
        head.right.right = new Node(1);
        head.left.left.right = new Node(1);
        printTree(head);

    }

}
"D:\Program Files\Java\jdk1.8.0_151\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\lib\idea_rt.jar=59499:D:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\bin" -Dfile.encoding=UTF-8 -classpath "D:\Program Files\Java\jdk1.8.0_151\jre\lib\charsets.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\deploy.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\access-bridge-64.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\cldrdata.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\dnsns.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jaccess.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jfxrt.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\localedata.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\nashorn.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunec.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunjce_provider.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunmscapi.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunpkcs11.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\zipfs.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\javaws.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jce.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jfr.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jfxswt.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\jsse.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\management-agent.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\plugin.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\resources.jar;D:\Program Files\Java\jdk1.8.0_151\jre\lib\rt.jar;D:\Java\algorithm\算法和数据结构体系学习班代码\算法和数据结构体系学习班代码\bin" class11.Code04_PrintBinaryTree
Binary Tree:
                                        v66v       
                        v3v       
                                     ^55555555^    
       H1H       
                   ^-222222222^   
                                                         v777v      
                                    ^-2147483648^  

Binary Tree:
                                         v6v       
                        v3v       
                                         ^5^       
       H1H       
                        ^2^       
                                                          v7v       
                                         ^4^       

Binary Tree:
                                         v1v       
                        v1v       
                                         ^1^       
       H1H       
                        ^1^       
                                                          v1v       
                                         ^1^       


Process finished with exit code 0

看结果例子:

* H1H根节点 第一排
* V1v 表示左边一排下方离我最近的跟我连接
* ^1^ 表示左边一排上方理我最近的跟我连接

顺时针旋转90度。就是实际二叉树结构

九、求二叉树最宽的层有多少个节点

package class11;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;

/**
 * 求二叉树最宽的层有多少个节点
 */
public class TreeMaxWidth {

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

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

    //方法一:利用哈希表存储每个节点所在层数,同步每层的节点,保存最大值
    public static int maxWidthUseMap(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 curLevel = 1;
        int curLevelNodes = 0;
        int max = 0;
        while(!queue.isEmpty()){
            //队列弹出节点,并获取该节点的层数
            Node cur = queue.poll();
            int curNodeLevel = map.get(cur);
            //如果节点的左右节点非空,那么就将子节点入队列,然后添加到哈希表,层数就是当前层数+1
            if(cur.left != null){
                queue.add(cur.left);
                map.put(cur.left,curNodeLevel+1);
            }
            if(cur.right != null){
                queue.add(cur.right);
                map.put(cur.right,curNodeLevel+1);
            }
            //如果当前节点层数与当前遍历的所在层数相等,那么当前层数+1
            if(curNodeLevel == curLevel){
                curLevelNodes++;
            }else{
                //不同层,说明就来到了下一层,刷新目前最大值层数个数, 层数+1,当前层数归1
                max = Math.max(max,curLevelNodes);
                curLevel++;
                curLevelNodes = 1;
            }
        }
        //最后退出 最后一层是curLevelNode++直到空退出,没有进行最大值判断,最后需要最大值
        max = Math.max(max,curLevelNodes);
        return max;
    }

    //方法二:不用哈希表,有限辅助节点变量 主要就是保存当前层末节点和下一层的末节点
    public static int maxWidthNoMap(Node head){
        if(head == null){
            return 0;
        }
        Queue<Node>queue = new LinkedList<>();
        queue.add(head);
        //辅助变量 当前层末节点、下一层末节点、当前层节点数、层数最大值
        Node curEnd = head;
        Node nextEnd = null;
        int curLevelNodes = 0;
        int max = 0;
        while(!queue.isEmpty()){
            //弹出队列节点,当前节点左右节点非空,那么就子节点入队列,并且刷新nextEnd节点
            Node cur = queue.poll();
            if(cur.left != null){
                queue.add(cur.left);
                nextEnd = cur.left;
            }
            if(cur.right != null){
                queue.add(cur.right);
                nextEnd = cur.right;
            }
            //刷新当前节点数+1
            curLevelNodes++;
            //如果当前节点来到了当前层的末节点 那么就要下移到下一层
            if(cur == curEnd){
                //刷新以往层的最大值,
                max = Math.max(max,curLevelNodes);
                //当前层节点清空
                curLevelNodes = 0;
                //然后要将下一层的末节点给到curEnd当前层
                curEnd = nextEnd;
            }
        }
        return max;
    }

    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    public static void main(String[] args) {
        int maxLevel = 10;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (maxWidthUseMap(head) != maxWidthNoMap(head)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");

    }
}

十、给你二叉树中的某个节点,返回该节点的后继节点

二叉树结构如下定义:
Class Node {
Vvalue;
Nodeleft;
Noderight;
Nodeparent;
}
给你二叉树中的某个节点,返回该节点的后继节点
package class11;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;

/**
 * 求二叉树最宽的层有多少个节点
 */
public class TreeMaxWidth {

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

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

    //方法一:利用哈希表存储每个节点所在层数,同步每层的节点,保存最大值
    public static int maxWidthUseMap(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 curLevel = 1;
        int curLevelNodes = 0;
        int max = 0;
        while(!queue.isEmpty()){
            //队列弹出节点,并获取该节点的层数
            Node cur = queue.poll();
            int curNodeLevel = map.get(cur);
            //如果节点的左右节点非空,那么就将子节点入队列,然后添加到哈希表,层数就是当前层数+1
            if(cur.left != null){
                queue.add(cur.left);
                map.put(cur.left,curNodeLevel+1);
            }
            if(cur.right != null){
                queue.add(cur.right);
                map.put(cur.right,curNodeLevel+1);
            }
            //如果当前节点层数与当前遍历的所在层数相等,那么当前层数+1
            if(curNodeLevel == curLevel){
                curLevelNodes++;
            }else{
                //不同层,说明就来到了下一层,刷新目前最大值层数个数, 层数+1,当前层数归1
                max = Math.max(max,curLevelNodes);
                curLevel++;
                curLevelNodes = 1;
            }
        }
        //最后退出 最后一层是curLevelNode++直到空退出,没有进行最大值判断,最后需要最大值
        max = Math.max(max,curLevelNodes);
        return max;
    }

    //方法二:不用哈希表,有限辅助节点变量 主要就是保存当前层末节点和下一层的末节点
    public static int maxWidthNoMap(Node head){
        if(head == null){
            return 0;
        }
        Queue<Node>queue = new LinkedList<>();
        queue.add(head);
        //辅助变量 当前层末节点、下一层末节点、当前层节点数、层数最大值
        Node curEnd = head;
        Node nextEnd = null;
        int curLevelNodes = 0;
        int max = 0;
        while(!queue.isEmpty()){
            //弹出队列节点,当前节点左右节点非空,那么就子节点入队列,并且刷新nextEnd节点
            Node cur = queue.poll();
            if(cur.left != null){
                queue.add(cur.left);
                nextEnd = cur.left;
            }
            if(cur.right != null){
                queue.add(cur.right);
                nextEnd = cur.right;
            }
            //刷新当前节点数+1
            curLevelNodes++;
            //如果当前节点来到了当前层的末节点 那么就要下移到下一层
            if(cur == curEnd){
                //刷新以往层的最大值,
                max = Math.max(max,curLevelNodes);
                //当前层节点清空
                curLevelNodes = 0;
                //然后要将下一层的末节点给到curEnd当前层
                curEnd = nextEnd;
            }
        }
        return max;
    }

    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    public static void main(String[] args) {
        int maxLevel = 10;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (maxWidthUseMap(head) != maxWidthNoMap(head)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");

    }
}

十一、折纸条问题,折N次,展开后从上到下打印折痕顺序

请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。
给定一个输入参数N,代表纸条都从下边向上方连续对折N次。请从上到下打印所有折痕的方向。
例如:N=1时,打印:down N=2时,打印: down down up

图例:

代码演示:

package class11;

/**
 * 请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。 如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。
 * 给定一个输入参数N,代表纸条都从下边向上方连续对折N次。 请从上到下打印所有折痕的方向。
 * 例如:N=1时,打印: down N=2时,打印: down down up
 */
public class PaperFolding {
    public static void printAllFolds(int N) {
        //递归调用程序。 中序遍历,初始默认在第一层,N层,第一层的折痕是下折痕,赋值true
        process(1, N, true);
        System.out.println();
    }

    // 当前你来了一个节点,脑海中想象的!
    // 这个节点在第i层,一共有N层,N固定不变的
    // 这个节点如果是凹的话,down = T
    // 这个节点如果是凸的话,down = F
    // 函数的功能:中序打印以你想象的节点为头的整棵树!
    public static void process(int i, int N, boolean down) {
        if (i > N) {
            //假如层数越界了,那么就退出
            return;
        }

        //折痕的特点是,每一次都会在当前已有的每个折痕的上下边分别多出 下折痕与上折痕,该特点可以用二叉树表示,第一次折痕为根节点,第二次生成的折痕是第二层节点...
        //下折痕,我们则定义true 上折痕 我们定义false
        //其折痕特征从上往下就是一个二叉树的中序遍历  左中右,左节点折痕就是下折痕,右节点就是上折痕
        //明确的规则:根节点是凹,左子树的根节点是凹,右子树的根节点是凸
        process(i + 1, N, true);
        System.out.print(down == true ? "凹 " : "凸 ");
        process(i + 1, N, false);
    }


    public static void main(String[] args) {
        int N = 3;
        printAllFolds(N);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/382127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于tsfresh包的单类时间序列特征提取

前言 时间序列特征提取包中tsfresh较为流行&#xff0c;但是其官方教程给出的例子是机器人故障的数据集&#xff0c;其中的id列为各组不同的实验。然后我就一直在想能否做单类的&#xff0c;比如电力预测&#xff0c;或者是某一条街道的交通预测&#xff0c;但是翻遍了文档都没…

Linux安装nginx详细步骤

1.安装依赖包//一键安装上面四个依赖yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel2.下载并解压安装包//创建一个文件夹 mkdir /usr/local/nginx cd /usr/local/nginx //下载tar包 wget http://nginx.org/download/nginx-1.18.0.tar.gz tar -xvf nginx…

蓝牙调试工具集合汇总

BLE 该部分主要分享一下常用的蓝牙调试工具&#xff0c;方便后续蓝牙抓包及分析。 目录 1 hciconfig 2 hcitool 3 hcidump 4 hciattach 5 btmon 6 bluetoothd 7 bluetoothctl 1 hciconfig 工具介绍&#xff1a;hciconfig&#xff0c;HCI 设备配置工具 命令格式&…

金融行业数据模型

一、Teradata FS-LDM Teradata 公司基于金融业务发布的FS-LDM&#xff08;Financial Servies Logical Data Model&#xff09; 十大主题&#xff1a;当事人、产品、协议、事件、资产、财务、机构、地域、营销、渠道。 1、当事人&#xff08;Party&#xff09; 银行所服务的任…

学习.NET MAUI Blazor(七)、实现一个真正的ChatGPT聊天应用

今天在新闻上看到一条消息&#xff0c;OpenAI已经开放了ChatGPT的接口&#xff0c;也就是GPT-3.5&#xff0c;对比原来的GPT-3&#xff0c;增加了gpt-3.5-turbo、gpt-3.5-turbo-0301两个模型。 gpt-3.5-turbo&#xff1a;使用最新的GPT-3.5模型&#xff0c;并针对聊天进行了优…

和风SDK查询城市ID(保姆级教程)

android studio版本&#xff1a;2021.2.1例程名&#xff1a;hfserachcityid这几天没什么事做&#xff0c;而且我原来那个“项目”因为免费api不能用了&#xff0c;只能改为和风的免费api,但需要申请&#xff0c;而且还要城市ID&#xff0c;玩天气的基本都知道城市ID这个东西&am…

公司章程包括了哪些内容

一、公司章程包括了哪些内容 《中华人民共和国公司法》第11条规定&#xff1a;“设立公司必须依法制定公司章程。公司章程对公司、股东、董事、监事、高级管理人员具有约束力。”明确地强调了公司章程对于公司的重要性&#xff0c;公司章程对于公司而言不但是股东合意达成的协…

葵花8号卫星数据简介与下载笔记

1、葵花8号卫星数据简介JMA于2015年7月7日开始运营Himawari-8&#xff0c;以取代MTSAT-2&#xff08;也称为Himawari-7&#xff09;。 Himawari-9号卫星于2017年3月10日开始后备运行。两颗卫星都位于向东约140.7度的轨道上&#xff0c;并将观测东亚和西太平洋区域15年。 源自Hi…

【项目实战】IDEA常用快捷键汇总

一、修改为Eclipse的快捷键 相信很多朋友跟我一样&#xff0c; 都是习惯了eclipse的快捷键&#xff0c;没错&#xff0c;习惯这东西真的很难改&#xff01;IDEA非常强大&#xff0c;支持我们修改IDEA中的keymap为Eclipse的快捷键&#xff01;友好又贴心&#xff0c;有没有&…

大数据框架之Hadoop:MapReduce(四)Hadoop数据压缩

4.1概述 1、压缩概述 压缩技术能够有效减少底层存储系统&#xff08;HDFS&#xff09;读写字节数。压缩提高了网络带宽和磁盘空间的效率。在运行MR程序时&#xff0c;IO操作、网络数据传输、shuffle和Merge要花大量的时间&#xff0c;尤其是数据规模很大和工作负载密集的情况…

3月2日第壹简报,星期四,农历二月十一

3月2日第壹简报&#xff0c;星期四&#xff0c;农历二月十一坚持阅读&#xff0c;静待花开1. 第三次延期&#xff01;财政部&#xff1a;对于购置期在2023年的新能源汽车继续免征车辆购置税。2. 我国2月份制造业PMI为52.6% &#xff0c;创2012年4月以来新高。3. 全国地级市财力…

深入浅出消息队列MSMQ

消息队列MSMQ&#xff0c;相信稍有开发经验的小伙伴都了解一些。开始讲解之前&#xff0c;我们先弄清楚一件事&#xff0c;为什么我们要使用MSMQ&#xff1a; 您可能认为您能够通过一个简单的数据库表(一个应用程序往其中写入数据&#xff0c;另一个应用程序从中读取数据)来应用…

采编式AIGC视频生产流程编排实践

作者 | 百度人工智能创作团队 导读 本文从业务出发&#xff0c;系统介绍了采编式 TTV的实现逻辑和实现路径。结合业务拆解&#xff0c;实现了一个轻量级服务编排引擎&#xff0c;有效实现业务诉求、高效支持业务扩展。 全文6451字&#xff0c;预计阅读时间17分钟。 01 背景 近…

WebRTC之RTP封装与解封装

1 前言rtp_rtcp模块作为Webrtc组件中非常重要的组成部分&#xff0c;首先是对应rtp和rtcp的封装与解封装&#xff0c;第二部分是对QOS各种策略的支持都离不开rtcp的控制协议。这里首先进行协议封装的探讨。2 RTP协议解析各个音视频的大佬对下面这张RTP协议图应该并不陌生&#…

ChatGPT到底是个啥?简析ChatGPT!

目录 ​编辑 1. ChatGPT到底是个啥&#xff1f; 1.1. 简介 1.2 玩法 1.2.1.生成公司理念、生成广告标语 1.2.2.写小说写故事写情书 1.2.3.生成自媒体文案 1.2.4.写代码 2.简析ChatGPT 2.1.ChatGPT核心能力 2.2.ChatGPT进化史 2.2.1.历史沿革 2.2.2.算法 2.3.ChatGPT特…

k8s学习之路 | Pod 基础

文章目录Pod 基础认知什么是 PodPod 的示例 yamlPod 的形式Pod 的多容器协同Pod 的生命周期容器的类型应用容器初始化容器临时容器静态 Pod什么是静态 Pod静态 Pod 位置Pod 探针机制探针类型Probe 配置项探针案例Pod 基础认知 什么是 Pod https://kubernetes.io/zh-cn/docs/c…

Word处理控件Aspose.Words功能演示:使用 Java 合并 MS Word 文档

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

Overlay网络技术

大家好&#xff0c;我是技福的小咖老师。 Overlay网络是通过网络虚拟化技术&#xff0c;在同一张Underlay网络上构建出的一张或者多张虚拟的逻辑网络。不同的Overlay网络虽然共享Underlay网络中的设备和线路&#xff0c;但是Overlay网络中的业务与Underlay网络中的物理组网和互…

aardio - 【库】简单信息框

昨晚得知aardio作者一鹤的妻子病情严重&#xff0c;深感悲痛。今日给一鹤捐赠少许&#xff0c;望其妻能挺过难关&#xff0c;早日康复。 aardio是一个很好的编程工具&#xff0c;我非常喜欢&#xff0c;这两年也一直在用。虽然未曾用其获利&#xff0c;但其灵活的语法&#xff…

操作系统真相还原——第7章 中断

中断&#xff1a;CPU 暂停正在执行的程序&#xff0c;转而去执行处理该事件的程序&#xff0c;当这段程序执行完毕后&#xff0c; CPU 继续执行刚才的程序。 通常&#xff0c;中断牺牲的是个体的时间&#xff0c;但可以实现多设备的并发&#xff0c;从而提高系统效率 操作系统…