数据结构——用Java实现二分搜索树

目录

一、树

二、二分搜索树

1.二叉树

2.二分搜索树

三、代码实现

1.树的构建

2.获取树中结点的个数

3.添加元素

4.查找元素

(1)查找元素是否存在

(2)查找最小元素

(3)查找最大元素

5.二分搜索树的遍历

(1)前序遍历:

(2)中序遍历:

(3)后序遍历:

(4)层序遍历:

6.删除操作

(1)删除最小元素

(2)删除最大元素

(3)删除任意元素

(4)删除根节点


一、树

        树结构本身是一种天然的组织结构

        是一个高效的查询内容的结构

二、二分搜索树

1.二叉树

特点:1.只有唯一的一个根节点

           2.每个结点最多有两个孩子

           3.每个结点最多有一个父亲

           4.二叉树具有天然的递归结构(左右子树也是二叉树)

           5.叶子结点出现在二叉树的最底层,除叶子结点之外的其它结点都有两个孩子结点。

2.二分搜索树

是特殊的二叉树

每个节点都大于左子树的所有结点,都小于右子树的所有结点

注意:存储的元素必须具有可比性

因为二分搜索树也是二叉树,也具有天然的递归结构,所以许多方法都可以使用递归的思想去实现

三、代码实现

1.树的构建

需要的元素有:根节点,结点,频率(如果添加的元素有重复元素),结点的值,索引,结点个数

//树的结点
    private static class Node<T> {
        private final T ele;//结点的值
        private int frequence;//频率
        private Node<T> left, right;//分别指向左右孩子的索引

        public Node(T ele) {
            this.ele = ele;
            this.left = this.right = null;
        }

    }

    //树对应的属性
    private Node<T> root;//树的根节点
    private int size;//结点的个数

    //构建树
    public BinearySeachTree() {
        this.root = null;
        this.size = 0;
    }

在给元素添加泛型后,就不能直接比较,所以在开始就继承Comparable来实现元素的比较

public class BinearySeachTree<T extends Comparable<T>>{

}

2.获取树中结点的个数

//获取树中结点的个数
    public int getSize() {
        return this.size;
    }

3.添加元素

将元素添加到二分搜索树的过程中,要注意将大的元素放在结点的右边,小的元素放在左边

再添加元素时,需要找到对应的位置,则可以使用递归的思想。

如果添加的值小于结点的值,则查找结点左孩子,如果还是小于结点,则继续查找

//向树中添加结点
    public void add(T ele) {
        //更新根结点
        this.root = addDG(this.root, ele);
    }

    //语义:向以root为根的二分搜索树中添加元素ele
    private Node<T> addDG(Node<T> root, T ele) {
        //递归终止条件
        if (root == null) {
            this.size++;
            return new Node<T>(ele);
        }
        //递归操作
        if (root.ele.compareTo(ele) > 0) {
            root.left = addDG(root.left, ele);
        } else if (root.ele.compareTo(ele) < 0) {
            root.right = addDG(root.right, ele);
        } else {
            //更新频率
            root.frequence++;
        }
        return root;
    }

4.查找元素

(1)查找元素是否存在

        查找元素是否在二叉树中,查找每一个结点,如果查找元素比当前节点小,就在左子树里重新查找,如果查找元素比当前节点大,就在右子树里重新查找

 //查询的方法
    public boolean search(T ele) {
        return searchDG(this.root, ele);
    }

    //语义:从以root为根的二分搜索树中查找元素ele
    private boolean searchDG(Node<T> root, T ele) {
        //递归终止的条件
        if (root == null) {
            return false;
        }
        //递归操作
        if (root.ele.compareTo(ele) == 0) {
            return true;
        } else if (root.ele.compareTo(ele) > 0) {
            return searchDG(root.left, ele);
        } else {
            return searchDG(root.right, ele);
        }
    }

(2)查找最小元素

        二分搜索树中最左边的元素

 //找树中的最小元素
    public T getMinValue() {
        if (this.isEmpty()) {
            return null;
        }
        Optional<Node<T>> optional = getMinNode();
        return optional.get().ele;
    }

//直接查找
private Optional<Node<T>> getMinNode() {
        if (this.root == null) {
            return Optional.empty();
        }
        //一直向左查找
        Node<T> node = this.root;
        while (node.left != null) {
            node = node.left;
        }
        return Optional.of(node);
    }

//利用递归方法查找
    //语义:在以Node为根结点的树中查找最小结点
    private Optional<Node<T>> getMinNode(Node<T> node) {
        if (node.left == null) {
            return Optional.of(node);
        }
        return getMinNode(node.left);
    }

(3)查找最大元素

        二分搜索树中最右边的元素

//找树中的最大元素
    public T getMaxValue() {
        if (this.isEmpty()) {
            return null;
        }
        Optional<Node<T>> optional = getMaxNode(this.root);
        return optional.get().ele;

    }

 //语义:在以Node为根结点的树中查找最大结点
    private Optional<Node<T>> getMaxNode(Node<T> node) {
        if (node.right == null) {
            return Optional.of(node);
        }
        return getMaxNode(node.right);
    }

5.二分搜索树的遍历

树的遍历有四种:前序遍历;中序遍历;后序遍历;层序遍历

(1)前序遍历:

首先打印根节点,然后遍历左子树,最后是右子树

【28,16,13,22,30,29,42】

//前序遍历
    public void preTravel() {
        List<AbstractMap.SimpleEntry<T, Integer>> list = new ArrayList<>();
        preTravelDG(this.root, list);
        String str = list.stream().map(item -> "[" + item.getKey() + ":" + item.getValue() + "]").collect(Collectors.joining("-"));
        System.out.println(str);
    }

 //前序遍历以root为根的树,讲解稿保存在list中
    private void preTravelDG(Node<T> root, List<AbstractMap.SimpleEntry<T, Integer>> list) {
        //递归终止条件
        if (root == null) {
            return;
        }
        //递归操作
        list.add(new AbstractMap.SimpleEntry<>(root.ele, root.frequence));
        //遍历左子树
        preTravelDG(root.left, list);
        //遍历右子树
        preTravelDG(root.right, list);
    }

(2)中序遍历:

先遍历左子树,在打印中间结点,最后遍历右子树

【13,16,22,28,29,30,42】

//中序遍历
    public void midTravel() {
        List<AbstractMap.SimpleEntry<T, Integer>> list = new ArrayList<>();
        midTravelDG(this.root, list);
        String str = list.stream().map(item -> item.toString()).collect(Collectors.joining("-"));
        System.out.println(str);
    }

//中序遍历以root为根的树,讲解稿保存在list中
    private void midTravelDG(Node<T> root, List<AbstractMap.SimpleEntry<T, Integer>> list) {
        //递归终止条件
        if (root == null) {
            return;
        }
        //递归操作
        //遍历左子树
        preTravelDG(root.left, list);
        list.add(new AbstractMap.SimpleEntry<>(root.ele, root.frequence));
        //遍历右子树
        preTravelDG(root.right, list);
    }

(3)后序遍历:

先遍历左子树,在遍历右子树,最后在打印中间结点

【13,22,16,29,42,30,28】

 //后序遍历
    public void sufTravel() {
        List<AbstractMap.SimpleEntry<T, Integer>> list = new ArrayList<>();
        sufTravelDG(this.root, list);
        String str = list.stream().map(item -> item.toString()).collect(Collectors.joining("-"));
        System.out.println(str);
    }

 //后序遍历以root为根的树,讲解稿保存在list中
    private void sufTravelDG(Node<T> root, List<AbstractMap.SimpleEntry<T, Integer>> list) {
        //递归终止条件
        if (root == null) {
            return;
        }
        //递归操作
        //遍历左子树
        preTravelDG(root.left, list);
        //遍历右子树
        preTravelDG(root.right, list);
        list.add(new AbstractMap.SimpleEntry<>(root.ele, root.frequence));
    }

可以看到,先中后序遍历的代码区别只是在递归最后将元素添加到list的位置不同而已

(4)层序遍历:

一层一层的打印

【28,16,30,13,22,29,42】

//层序遍历
    public void levelTravel() {
        //判断树是否为空
        if (this.isEmpty()) {
            return;
        }
        Queue<AbstractMap.SimpleEntry<Node<T>, Integer>> queue = new LinkedList<>();
        //1.先将根结点入队
        queue.add(new AbstractMap.SimpleEntry<>(this.root, 1));
        //2.遍历队列
        while (!queue.isEmpty()) {
            //2-1.出队
            AbstractMap.SimpleEntry<Node<T>, Integer> pair = queue.poll();
            //结点
            Node<T> node = pair.getKey();
            //层
            int level = pair.getValue();
            ;
            System.out.println("[val:" + node.ele + ",level:" + level + "]");
            //2-2.判断左右子树是否为空
            if (node.left != null) {
                queue.add(new AbstractMap.SimpleEntry<>(node.left, level + 1));
            }
            if (node.right != null) {
                queue.add(new AbstractMap.SimpleEntry<>(node.right, level + 1));
            }
        }
    }

6.删除操作

删除的操作中,需要注意删除后二分搜索树也会因此改变,所以要分情况讨论

(1)删除最小元素

删除最小元素并不需要改变树,只需要失去关联关系即可

 //从树中删除最小的结点
    public T removeMinNode() {
        T result = getMinValue();
        if (result == null) {
            return null;
        }
        //更新根结点
        this.root = removeMinNode(this.root);
        return result;
    }

    //语义:从以Node为根的二分搜索树中删除元素最小的结点
    private Node<T> removeMinNode(Node<T> node) {
        //递归终止条件
        if (node.left == null) {
            //删除操作
            //1.记录右子树
            Node<T> rightTree = node.right;
            //失去关联关系
            node.right = null;
            //3.跟新size
            this.size--;
            return rightTree;
        }
        //递归操作
        node.left = removeMinNode(node.left);
        return node;
    }

(2)删除最大元素

跟删除最小元素一样,只需要失去关联关系即可

//从树中删除最大的结点
    public T removeMaxNode() {
        T result = getMaxValue();
        if (result == null) {
            return null;
        }
        //更新根结点
        this.root = removeMaxNode(this.root);
        return result;
    }

    //语义:从以Node为根的二分搜索树中删除元素最大的结点
    private Node<T> removeMaxNode(Node<T> node) {
        //递归终止条件
        if (node.right == null) {
            //删除操作
            //1.记录左子树
            Node<T> leftTree = node.left;
            //失去关联关系
            node.left = null;
            //3.跟新size
            this.size--;
            return leftTree;
        }
        //递归操作
        node.right = removeMaxNode(node.right);
        return node;
    }

(3)删除任意元素

在删除任意元素中,需要考虑删除结点有没有左右子树

//语义:从以Node为根的二分搜索树中删除值为ele的结点
    private Node<T> remove(Node<T> node, T ele) {
        //递归终止的条件
        //没有找到
        if (node == null) {
            return null;
        }
        //找到了
        if (node.ele.compareTo(ele) == 0) {
            this.size--;
            //Node就是要删除的结点
            if (node.left == null) {
                Node<T>rightNode=node.right;
                node.right=null;
                return rightNode;
            } else if (node.right == null) {
                Node<T>leftNode=node.left;
                node.left=null;
                return leftNode;
            } else {
                Node<T> suffixNode = getMinNode(node.right).get();
                suffixNode.right=removeMinNode(node.right);
                suffixNode.left=node.left;
                this.size++;
                //失去关联关系
                node.left=node.right=null;
                return suffixNode;
            }
        }
        //递归操作
        if (node.ele.compareTo(ele) > 0) {
            node.left = remove(node.left, ele);
        } else {
            node.right = remove(node.right, ele);
        }
        return node;
    }

(4)删除根节点

直接删除关联关系即可

 //删除根节点
    public void removeRoot(){
        if(this.root==null){
            return;
        }
        remove(this.root.ele);
    }

四、完整代码

package com.algo.lesson.lesson04;

import java.util.*;
import java.util.stream.Collectors;

//二分搜索树
/*
保存到结点中的元素值必须具有可比性
 */
public class BinearySeachTree<T extends Comparable<T>> {
    //树的结点
    private static class Node<T> {
        private final T ele;//结点的值
        private int frequence;//频率
        private Node<T> left, right;//分别指向左右孩子的索引

        public Node(T ele) {
            this.ele = ele;
            this.left = this.right = null;
        }

    }

    //树对应的属性
    private Node<T> root;//树的根节点
    private int size;//结点的个数

    //构建树
    public BinearySeachTree() {
        this.root = null;
        this.size = 0;
    }

    //获取树中结点的个数
    public int getSize() {
        return this.size;
    }

    //向树中添加结点
    public void add(T ele) {
        //更新根结点
        this.root = addDG(this.root, ele);
    }

    //语义:向以root为根的二分搜索树中添加元素ele
    private Node<T> addDG(Node<T> root, T ele) {
        //递归终止条件
        if (root == null) {
            this.size++;
            return new Node<T>(ele);
        }
        //递归操作
        if (root.ele.compareTo(ele) > 0) {
            root.left = addDG(root.left, ele);
        } else if (root.ele.compareTo(ele) < 0) {
            root.right = addDG(root.right, ele);
        } else {
            //更新频率
            root.frequence++;
        }
        return root;
    }

    //查询的方法
    public boolean search(T ele) {
        return searchDG(this.root, ele);
    }

    //语义:从以root为根的二分搜索树中查找元素ele
    private boolean searchDG(Node<T> root, T ele) {
        //递归终止的条件
        if (root == null) {
            return false;
        }
        //递归操作
        if (root.ele.compareTo(ele) == 0) {
            return true;
        } else if (root.ele.compareTo(ele) > 0) {
            return searchDG(root.left, ele);
        } else {
            return searchDG(root.right, ele);
        }
    }

    //二分搜索树的遍历

    //前序遍历
    public void preTravel() {
        List<AbstractMap.SimpleEntry<T, Integer>> list = new ArrayList<>();
        preTravelDG(this.root, list);
        String str = list.stream().map(item -> "[" + item.getKey() + ":" + item.getValue() + "]").collect(Collectors.joining("-"));
        System.out.println(str);
    }

    //中序遍历
    public void midTravel() {
        List<AbstractMap.SimpleEntry<T, Integer>> list = new ArrayList<>();
        midTravelDG(this.root, list);
        String str = list.stream().map(item -> item.toString()).collect(Collectors.joining("-"));
        System.out.println(str);
    }

    //后序遍历
    public void sufTravel() {
        List<AbstractMap.SimpleEntry<T, Integer>> list = new ArrayList<>();
        sufTravelDG(this.root, list);
        String str = list.stream().map(item -> item.toString()).collect(Collectors.joining("-"));
        System.out.println(str);
    }

    //前序遍历以root为根的树,讲解稿保存在list中
    private void preTravelDG(Node<T> root, List<AbstractMap.SimpleEntry<T, Integer>> list) {
        //递归终止条件
        if (root == null) {
            return;
        }
        //递归操作
        list.add(new AbstractMap.SimpleEntry<>(root.ele, root.frequence));
        //遍历左子树
        preTravelDG(root.left, list);
        //遍历右子树
        preTravelDG(root.right, list);
    }

    //中序遍历以root为根的树,讲解稿保存在list中
    private void midTravelDG(Node<T> root, List<AbstractMap.SimpleEntry<T, Integer>> list) {
        //递归终止条件
        if (root == null) {
            return;
        }
        //递归操作
        //遍历左子树
        preTravelDG(root.left, list);
        list.add(new AbstractMap.SimpleEntry<>(root.ele, root.frequence));
        //遍历右子树
        preTravelDG(root.right, list);
    }

    //后序遍历以root为根的树,讲解稿保存在list中
    private void sufTravelDG(Node<T> root, List<AbstractMap.SimpleEntry<T, Integer>> list) {
        //递归终止条件
        if (root == null) {
            return;
        }
        //递归操作
        //遍历左子树
        preTravelDG(root.left, list);
        //遍历右子树
        preTravelDG(root.right, list);
        list.add(new AbstractMap.SimpleEntry<>(root.ele, root.frequence));
    }

    //判断树是否为空
    public boolean isEmpty() {
        return this.size == 0;
    }

    //层序遍历
    public void levelTravel() {
        //判断树是否为空
        if (this.isEmpty()) {
            return;
        }
        Queue<AbstractMap.SimpleEntry<Node<T>, Integer>> queue = new LinkedList<>();
        //1.先将根结点入队
        queue.add(new AbstractMap.SimpleEntry<>(this.root, 1));
        //2.遍历队列
        while (!queue.isEmpty()) {
            //2-1.出队
            AbstractMap.SimpleEntry<Node<T>, Integer> pair = queue.poll();
            //结点
            Node<T> node = pair.getKey();
            //层
            int level = pair.getValue();
            ;
            System.out.println("[val:" + node.ele + ",level:" + level + "]");
            //2-2.判断左右子树是否为空
            if (node.left != null) {
                queue.add(new AbstractMap.SimpleEntry<>(node.left, level + 1));
            }
            if (node.right != null) {
                queue.add(new AbstractMap.SimpleEntry<>(node.right, level + 1));
            }
        }
    }

    //找树中的最小元素
    public T getMinValue() {
        if (this.isEmpty()) {
            return null;
        }
        Optional<Node<T>> optional = getMinNode();
        return optional.get().ele;
    }

    //找树中的最大元素
    public T getMaxValue() {
        if (this.isEmpty()) {
            return null;
        }
        Optional<Node<T>> optional = getMaxNode(this.root);
        return optional.get().ele;

    }

    private Optional<Node<T>> getMinNode() {
        if (this.root == null) {
            return Optional.empty();
        }
        //一直向左查找
        Node<T> node = this.root;
        while (node.left != null) {
            node = node.left;
        }
        return Optional.of(node);
    }

    //递归
    //语义:在以Node为根结点的树中查找最小结点
    private Optional<Node<T>> getMinNode(Node<T> node) {
        if (node.left == null) {
            return Optional.of(node);
        }
        return getMinNode(node.left);
    }

    //语义:在以Node为根结点的树中查找最大结点
    private Optional<Node<T>> getMaxNode(Node<T> node) {
        if (node.right == null) {
            return Optional.of(node);
        }
        return getMaxNode(node.right);
    }

    //删除操作
    //从树中删除最小的结点
    public T removeMinNode() {
        T result = getMinValue();
        if (result == null) {
            return null;
        }
        //更新根结点
        this.root = removeMinNode(this.root);
        return result;
    }

    //语义:从以Node为根的二分搜索树中删除元素最小的结点
    private Node<T> removeMinNode(Node<T> node) {
        //递归终止条件
        if (node.left == null) {
            //删除操作
            //1.记录右子树
            Node<T> rightTree = node.right;
            //失去关联关系
            node.right = null;
            //3.跟新size
            this.size--;
            return rightTree;
        }
        //递归操作
        node.left = removeMinNode(node.left);
        return node;
    }

    //删除操作
    //从树中删除最大的结点
    public T removeMaxNode() {
        T result = getMaxValue();
        if (result == null) {
            return null;
        }
        //更新根结点
        this.root = removeMaxNode(this.root);
        return result;
    }

    //语义:从以Node为根的二分搜索树中删除元素最大的结点
    private Node<T> removeMaxNode(Node<T> node) {
        //递归终止条件
        if (node.right == null) {
            //删除操作
            //1.记录左子树
            Node<T> leftTree = node.left;
            //失去关联关系
            node.left = null;
            //3.跟新size
            this.size--;
            return leftTree;
        }
        //递归操作
        node.right = removeMaxNode(node.right);
        return node;
    }

    //删除任意结点
    public void remove(T ele) {
        //根据值查找结点
        this.root = remove(this.root, ele);
    }

    //语义:从以Node为根的二分搜索树中删除值为ele的结点
    private Node<T> remove(Node<T> node, T ele) {
        //递归终止的条件
        //没有找到
        if (node == null) {
            return null;
        }
        //找到了
        if (node.ele.compareTo(ele) == 0) {
            this.size--;
            //Node就是要删除的结点
            if (node.left == null) {
                Node<T>rightNode=node.right;
                node.right=null;
                return rightNode;
            } else if (node.right == null) {
                Node<T>leftNode=node.left;
                node.left=null;
                return leftNode;
            } else {
                Node<T> suffixNode = getMinNode(node.right).get();
                suffixNode.right=removeMinNode(node.right);
                suffixNode.left=node.left;
                this.size++;
                //失去关联关系
                node.left=node.right=null;
                return suffixNode;
            }
        }
        //递归操作
        if (node.ele.compareTo(ele) > 0) {
            node.left = remove(node.left, ele);
        } else {
            node.right = remove(node.right, ele);
        }
        return node;
    }

    //删除根节点
    public void removeRoot(){
        if(this.root==null){
            return;
        }
        remove(this.root.ele);
    }

}

五、例题

1.700. 二叉搜索树中的搜索

​​​​

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if(root==null){
            return null;
        }
        if(val==root.val){
            return root;
        }
        return searchBST(val<root.val?root.left:root.right,val);
    }
}

2.力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
//更新根结点
        return root = addDG(root, val);
    }

    //语义:向以root为根的二分搜索树中添加元素ele
    private TreeNode addDG(TreeNode root, int val) {
        //递归终止条件
        if (root == null) {
            return new TreeNode(val);
        }
        //递归操作
        if (root.val>val) {
            root.left = addDG(root.left, val);
        } else if (root.val<val) {
            root.right = addDG(root.right, val);
        }
        return root;
    }
}

3.力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        if (root == null) {
            return list;
        }
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            List<Integer> level = new ArrayList<Integer>();
            int temp = queue.size();
            for (int i = 1; i <= temp; i++) {
                TreeNode node = queue.poll();
                level.add(node.val);
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            list.add(level);
        }
        return list;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法39:统计全 1 子矩形(力扣1504)----单调栈

题目: 给你一个 m x n 的二进制矩阵 mat &#xff0c;请你返回有多少个 子矩形 的元素全部都是 1 。 示例 1&#xff1a; 输入&#xff1a;mat [[1,0,1],[1,1,0],[1,1,0]] 输出&#xff1a;13 解释&#xff1a; 有 6 个 1x1 的矩形。 有 2 个 1x2 的矩形。 有 3 个 2x1 的矩…

(2024|ICLR,MAD,真实数据与合成数据,自吞噬循环)自消耗生成模型变得疯狂

Self-Consuming Generative Models Go MAD 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 2. 自吞噬生成模型 2.1 自吞噬过程 2.2 自吞噬过程的变体 2.3 自吞噬循环中的偏…

Advanced EFS Data Recovery:恢复 Windows NTFS 中 EFS 加密文件

Advanced EFS Data Recovery 数据恢复软件可以破解 NTFS 加密&#xff0c;并解密受 Windows 加密文件系统 &#xff08;EFS&#xff09; 保护的文件。 Advanced EFS Data Recovery 功能列表 通过破解加密文件系统 &#xff08;EFS&#xff09; 来解除 NTFS 加密 解密转移到另…

Java面试题(11)

59.说一说springMVC的运行流程 1. 用户向服务器发送请求&#xff0c;请求被 Spring 前端控制 Servelt DispatcherServlet 捕获&#xff1b; 2. DispatcherServlet 对请求 URL 进行解析&#xff0c;得到请求资源标识符&#xff08;URI&#xff09;。然后根据该 URI&#xff0c;…

STM32 E18-D80NK红外避障传感器

E18-D80NK-N是一款红外光电传感器&#xff0c;它同时具备发射和接收功能。通过对发射光进行调制后发出&#xff0c;并通过接收头对反射光进行解调输出。 E18-D80NK-N采用了透镜来增强传感器的性能&#xff0c;使其能够检测更远的距离。根据红外光的特性&#xff0c;不同颜色的…

VitePress-04-文档中的表情符号的使用

说明 vitepress 的文档中是支持使用表情符号的&#xff0c;像 &#x1f602; 等常用的表情都是支持的。 本文就来介绍它的使用方式。 使用语法 语法 &#xff1a; :表情名称: 例如 &#xff1a; :joy: &#x1f602; 使用案例代码 # 体会【表情】的基本使用 > hello world …

22.Lambda 表达式

Lambda 表达式 1. 概况2. 函数式接口3. 格式3.1 完整格式3.2 省略格式 4. 代码示例5. 输出结果6. 注意事项 学习Lambda表达式之前最好先学会 匿名内部类 具体信息请查看 API 帮助文档 1. 概况 Lambda 表达式是一种在编程中用来表示匿名函数的简洁语法。它是基于函数式编程风格…

2024.1.27每日一题

LeetCode 最大合金数 2861. 最大合金数 - 力扣&#xff08;LeetCode&#xff09; 题目描述 假设你是一家合金制造公司的老板&#xff0c;你的公司使用多种金属来制造合金。现在共有 n 种不同类型的金属可以使用&#xff0c;并且你可以使用 k 台机器来制造合金。每台机器都需…

SpringBoot之JWT登录

JWT JSON Web Token&#xff08;JSON Web令牌&#xff09; 是一个开放标准(rfc7519)&#xff0c;它定义了一种紧凑的、自包含的方式&#xff0c;用于在各方之间以JSON对象安全地传输信息。此信息可以验证和信任&#xff0c;因为它是数字签名的。jwt可以使用秘密〈使用HNAC算法…

嵌入式学习第十三天

9.指针: &#xff08;1&#xff09;const指针 const 关键字 常量(只读) 1.const int *p; 2.int const *p; 1和2是等价的 const修饰 *p,指针变量p的值可以改变,但不能利用指针修改指向空间中的值 3.int *const p; const修饰 p,指针变量p的值不能改变…

【教程】极简Docker搭建“帕鲁幻兽PalWorld”服务器, 附资源

注意&#xff1a; 如果搭建在个人服务器或者内网中&#xff0c;需要做内网穿透&#xff0c;可以看这篇博客&#xff1a; 【教程】超详细安装和使用免费内网穿透软件Zerotier-One-CSDN博客文章浏览阅读523次&#xff0c;点赞8次&#xff0c;收藏8次。真的很详细https://blog.csd…

[设计模式Java实现附plantuml源码~结构型]树形结构的处理——组合模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

Mysql查询数据

1 基本查询语句 MySQL从数据表中查询数据的基本语句为SELECT语句。SELECT语句的基本格式是&#xff1a; 2 单表查询 2.1 查询所有字段 SELECT * FROM 表名; 2.2 在SELECT语句中指定所有字段 SELECT f_id, s_id ,f_name, f_price FROM fruits; 2.3 查询单个字段 SELECT 列名FR…

Ajax入门与使用

目录 ◆ AJAX 概念和 axios 使用 什么是 AJAX&#xff1f; 怎么发送 AJAX 请求&#xff1f; 如何使用axios axios 函数的基本结构 axios 函数的使用场景 1 没有参数的情况 2 使用params参数传参的情况 3 使用data参数来处理请求体的数据 4 上传图片等二进制的情况…

C数据类型

目录 1. 数据类型分类 2. 整数类型 3. 浮点类型 4. void 类型 5. 类型转换 1. 数据类型分类 在 C 语言中&#xff0c;数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间&#xff0c;以及如何解释存储的位模式。 C 中…

格外空间以设计带动凯迪仕品牌价值增长 | 揽获6项国际设计大奖

Kaadas凯迪仕专注于智能锁领域&#xff0c;作为一家集产品研发、制造、品牌、全球销售、安装、售后于一体的全产业链公司&#xff0c;致力于服务全球每一个家庭&#xff0c;以更优质的产品&#xff0c;为全球众多家庭带去高品质生活体验。基于新消费时代背景&#xff0c;传统空…

联想懂的通信×实在智能:共同探索智连融合AI创新发展路径

近日&#xff0c;联想集团副总裁/联想懂的通信CEO王帅、CFO周利军、COO&CPO邢海洋、CGO赵晨、CTO边毅等领导一行莅临杭州实在智能科技有限公司开展研讨座谈。 实在智能创始人&CEO孙林君、联合创始人&COO高扬、联合创始人&CMO张俊九、销售VP&运营商事业线负…

成都直播产业园核心优势全面解读,入驻天府锋巢直播产业基地都有哪些好处?

一文讲清&#xff01;成都直播产业园核心优势全面解读 企业入驻天府锋巢直播产业基地能获得哪些好处&#xff1f; 锋巢资讯&#xff5e;又来了&#xff5e;&#xff5e;&#xff5e; 今天&#xff0c;将为您全面解读成都产业园重点特色产业服务&#xff08;上&#xff09; 什…

vit细粒度图像分类(五)TransFC学习笔记

1.摘要 细粒度图像具有不同子类间差异小、相同子类内差异大的特点。现有网络模型在处理过程中存在特征提取能力不足、特征表示冗余和归纳偏置能力弱等问题&#xff0c;因此提出一种改进的 Transformer图像分类模型。 首先&#xff0c;利用外部注意力取代原 Transformer模型中的…

Java之Idea中创建Web项目

一、新建动态web项目 1、新建项目 2、选择创建动态web项目 3、项目命名 4、编辑index.jsp 二、配置Tomcat 1、新增tomcat服务器配置 2、选择服务器类型 3、配置服务器参数 4、部署项目 5、完成配置 6、启动运行 7、访问web项目 在浏览器地址栏输入&#xff1a; http://local…