当前位置: 首页 > news >正文

数据结构:树

树的基本定义:

是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做 “树” 是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

  • 每个节点有零个或多个子节点;
  • 没有父节点的节点称为根节点;
  • 每一个非根节点有且只有一个父节点;
  • 除了根节点外,每个子节点可以分为多个不相交的子树;

树的相关术语:

节点的度:

一个节点含有的子树的个数称为该节点的度;

叶节点:

度为0的节点称为叶节点,也可以叫做终端节点

分支节点:

度不为0的节点称为分支节点,也可以叫做非终端节点,显然除了叶子节点之外的节点都为分支节点。

节点的层次:

节点的层次为从节点到根节点的路径中边的条数,并且认为根节点的层次为0,因为根节点到自身的路径中边的条数为0

树的度:

树中所有节点的度的最大值

树的高度(深度):

结点的深度指从根节点(度为1)自顶向下逐层累加至该结点时的深度。树的深度是树中深度最大的结点的深度。

如下图,该树的深度为5

💡1、二叉树:

二叉树的定义就是每个节点最多有两个子节点

二叉树的设计:

代码:

public class TreeNode<Key,Value> {private TreeNode left; //左子节点private TreeNode right; //右子节点private Key key; //存储键private Value value;//存储值public TreeNode(TreeNode left, TreeNode right, Key key, Value value) {this.left = left;this.right = right;this.key = key;this.value = value;}
}

插入方法put实现思想
1如果当前树中没有任何一个节点,则直接把新节点当做根节点使用
2如果当前树不为空,则从根节点开始
3如果新节点的key小于当前节点的key,则继续找当前节点的左子节点;
4如果新节点的key大于当前节点的key,则继续找当前节点的右子节点;
5如果新节点的key等于当前节点的key,则树中已经存在这样的节点,替换该节点的value即可;
插入方法代码:
 

 //记录根节点private TreeNode root;//记录元素个数private int N;public void put(Key key,Value value){root = put(root, key, value); //如果是第一次插入 直接该节点为根节点}//重载递归插入元素public TreeNode put(TreeNode node,Key key,Value value){if (node==null){//如果传入节点为空 则代表当前树中没有元素node=new TreeNode(null,null,key,value);N++;return node;}else {//如果不为空 则需要判断key大小 决定新插入元素是在左子节点还是右子节点int i = key.compareTo(node.key);  //需要实现 Comparable<>泛型接口 x.compareTo(y) 若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。if (i<0){  //i<0 表示新插入key 小于父节点key 那么就需要插入左边node.left = put(node.left, key, value);N++;}if (i>0){ //i>0 表示新插入的key 大于父节点key 那么就需要插入到右边node.right=put(node.right,key,value); //递归调用N++;}if (i==0){//i=0 表示当前key 和传入key 相等 那么直接将value覆盖node.value=value;}}return node;

获取方法get实现思想
从根节点开始:
1如果要查询的key小于当前节点的key,则继续找当前节点的左子节点;
2如果要查询的key大于当前节点的key,则继续找当前节点的右子节点;
3如果要查询的key等于当前节点的key,则树中返回当前节点的value;
代码实现:
 

 //查询元素方法 根据key 返回valuepublic Value get(Key key){if (root==null){return null; //当树中为空时 直接返回空}return get(root,key);}//查找递归public Value get(TreeNode node,Key key){int i = key.compareTo(node.key); //和插入同理 进行比较if (i<0){//i<0 表示需要查找的key 比节点key小 那么就继续寻找该节点的左子节点return get(node.left, key);}if (i>0){//i>0 表示要查找的key 比节点的key大 那么就继续寻找该节点的右子节点return get(node.right,key);}else {//i=0 表示找到对应的ke 直接返回对应的valuereturn node.value;}}
删除方法delete实现思想
  1. 找到被删除节点;
  2. 找到被删除节点右子树的最小节点minNode
  3. 删除右子树的最小节点
  4. 让被删除节点的左子树称为minNode的左子树,被删除节点右子树同理;
  5. 让被删除节点的父节点指向最小结点minNode

但删除会碰到许多的情况,如下:

1.当找到最小子节点时,如果它还有右子节点,那么还需要将右子节点赋给最小子节点的父节点。

如下图所示,但删除节点2时,找到最小子节点5,但是5节点还有一个右子节点,那么就需要将右子节点重新赋值给最小子节点的父节点也就是图中的8节点。然后在将5节点替换2节点

这部分对应代码

                TreeNode sonNode=node.right;  //找到右子树根节点  从右子节点开始遍历TreeNode sonFather=node;while (sonNode.left!=null){ //然后遍历寻找右子节点的左子节点sonFather=sonNode;  //记录最小左节点的父节点  为了应对最小子节点还有右子节点用  //TODO: bug记录 --顺序错误  应该在sonNode赋值前先将Father赋值 --否则会导致栈溢出sonNode=sonNode.left; //直到找到最左节点 也就是右子树中最小的那个节点}TreeNode minNode=sonNode;//如果最小节点此有右子节点 那么需要将最小节点的右子节点 重新赋值给最小节点的父节点if (minNode.right!=null){sonFather.left=minNode.right;  //将最小子节点的父节点  指向该节点的右子节点minNode.right=null; //将minNode 的子节点断开  --------------->  TODO:bug记录点1   此处导致 栈溢出}

删除方法完整代码:

后续可以进一步优化,提取重复代码

  //删除元素方法 根据key删除  返回被删除元素valuepublic Value delete(Key key){if (root==null){return null;}return   delete(root,key,root);}//递归查找删除方法public Value delete(TreeNode node,Key key,TreeNode father){//同样先要进行查找int i = key.compareTo(node.key);if (i<0){//key比节点key小 继续找左子节点father=node; //父节点变化    -----》TODO bug记录  父节点忘记变化 导致一直是指向根节点return     delete(node.left,key,node);//将父节点也传入}else if (i>0){//key 比当前节点key大 继续找右子节点father=node;  //父节点变化return delete(node.right,key,node);//将父节点也传入}else {  //此时找到了需要删除的key//临时记录 被删除元素的 左节点和右节点 --》需要判空处理 对左右节点//如果发现该节点的左右子节点都为空 那么就直接进行删除即可if (node.left==null&&node.right==null){//如果是根节点  并且树中只有根节点的时候if (N==1){root=null;}if (node.equals(father.left)){father.left=null;  //如果该节点是父节点的左子节点 则直接删除}else {father.right=null; //如果是右子节点则直接 则值节删除}N--;return node.value;  //返回删除的元素}//到这一步 必定是右子节点为null  左子节点不为null的情况if (node.right==null){ //如果被删除元素右子节点为空  那么直接将被删除元素的左子节点替换即可if (node.equals(father.left)){father.left=node.left;}else {father.right=node.left;}N--;return node.value; //返回删除的元素} else { //到这一步就 是左右子节点都不为null的情况  然后从被删除元素的右子树开始遍历 直到找右子树中最小的元素TreeNode sonNode=node.right;  //找到右子树根节点  从右子节点开始遍历TreeNode sonFather=node;while (sonNode.left!=null){ //然后遍历寻找右子节点的左子节点sonFather=sonNode;  //记录最小左节点的父节点  为了应对最小子节点还有右子节点用  //TODO: bug记录 --顺序错误  应该在sonNode赋值前先将Father赋值 --否则会导致栈溢出sonNode=sonNode.left; //直到找到最左节点 也就是右子树中最小的那个节点}TreeNode minNode=sonNode;//如果最小节点此有右子节点 那么需要将最小节点的右子节点 重新赋值给最小节点的父节点if (minNode.right!=null){sonFather.left=minNode.right;  //将最小子节点的父节点  指向该节点的右子节点minNode.right=null; //将minNode 的子节点断开  --------------->  TODO:bug记录点1   此处导致 栈溢出}//到此所有情况已经判断完毕 可以执行节点删除if (node.equals(father.left)){father.left=minNode;minNode.left=node.left;minNode.right=node.right;  //进行删除操作}else {father.right=minNode;minNode.left=node.left;minNode.right=node.right; // 进行删除操作}N--;return node.value;  //返回被删除元素}}}
寻找最小值getMin实现思想

搞懂删除方法后,最小值思路就相比很简单了,一直循环或递归左子节点,直到为null即可。

  //寻找最小值public Value getMin(){if (root==null){return null;}TreeNode min=root;while (min.left!=null){min=min.left;}return min.value;}
寻找最大值getMax实现思想

与最小值方法同理,无非是从遍历左节点改为了右节点

  //寻找最大值public Value getMax(){if (root==null){return null;}TreeNode max=root;while (max.right!=null){max=max.right;}return max.value;}
二叉树遍历:

二叉树的遍历是树中很重要的一个部分了,由于树的结构特殊性,它没有办法从头开始依次向后遍历,所以存在如何遍历,也就是按照什么样的搜索路径进行遍历的问题。

1.前序遍历:

先访问根节点,然后再访问左子树,最后访问右子树

2.中序遍历:

先访问左子树,中间访问根节点,最后访问右子树

3.后序遍历:

先访问左子树,再访问右子树,最后访问根节点

1.前序遍历:

实现思路:

  1. 把当前结点key放入到队列中;
  2. 找到当前结点的左子树,如果不为空,则递归遍历左子树;
  3. 找到当前节点的右子树,如果不为空,则递归遍历右子树;

以该树为例,那么前序遍历的结果应该是:

10-2-1-8-5-3-4-6-9-12-11-16

中序遍历结果应该是:

2-1-8-5-3-4-6-9-10-12-11-16

后序遍历结果应该是:

2-1-8-5-3-4-6-9-12-11-16-10

实现代码:

   //前序遍历 从根节点开始——》左子树——》右子树public Queue<Key> preErgodic(){Queue<Key> keys=new Queue<>();preErgodic(root,keys);return keys;}//递归遍历 将遍历到的都添加在队列中private void preErgodic(TreeNode x,Queue<Key> key){if (x==null){return;}key.inQueue(x.key);if (x.left!=null){//如果左子节点不为空 则递归遍历左子节点preErgodic(x.left,key);}if (x.right!=null){preErgodic(x.right,key);}}

运行结果

    public static void main(String[] args) {BinaryTree<Integer,String> tree=new BinaryTree<>();tree.put(10,"张三");tree.put(2,"老二");tree.put(1,"老一");tree.put(8,"老八");tree.put(5,"老五");tree.put(9,"老九");tree.put(3,"老三");tree.put(6,"老六");tree.put(4,"老四");tree.put(12,"老十二");tree.put(11,"老十一");tree.put(16,"老十六");Queue<Integer> queue=tree.preErgodic();for (Integer integer : queue) {System.out.println(integer);}System.out.println("------------------中序遍历-------------------------");Queue<Integer> queueMid = tree.midErgodic();for (Integer integer : queueMid) {System.out.println(integer);}System.out.println("---------后序遍历-------------------------");Queue<Integer> queueAfter = tree.afterErgodic();for (Integer integer : queueAfter) {System.out.println(integer);}}
//运行结果
10
2
1
8
5
3
4
6
9
12
11
16------------------------------中序遍历-------------------------
2
1
8
5
3
4
6
9
10
12
11
16
------------------------------后序遍历-------------------------
2
1
8
5
3
4
6
9
12
11
16
10
2.中序遍历:
  1. 找到当前结点的左子树,如果不为空,则递归遍历左子树;
  2. 把当前结点key放入到队列中;
  3. 找到当前节点的右子树,如果不为空,则递归遍历右子树;

代码:

 //中序遍历 从左子树开始——》根节点——》右子树public Queue<Key> midErgodic(){Queue<Key> keys=new Queue<>();preErgodic(root,keys);return keys;}//递归遍历 将遍历到的都添加在队列中private void midErgodic(TreeNode x,Queue<Key> key){if (x==null){return;}//先找到左子节点if (x.left!=null){//如果左子节点不为空 则递归遍历左子节点preErgodic(x.left,key);}key.inQueue(x.key);if (x.right!=null){preErgodic(x.right,key);}}
3.后序遍历:
  1. 找到当前结点的左子树,如果不为空,则递归遍历左子树;
  2. 找到当前节点的右子树,如果不为空,则递归遍历右子树;
  3. 把当前结点key放入到队列中;
//后序遍历 从左子树开始——》右子树——》根节点public Queue<Key> afterErgodic(){Queue<Key> keys=new Queue<>();preErgodic(root,keys);return keys;}//递归遍历 将遍历到的都添加在队列中private void afterErgodic(TreeNode x,Queue<Key> key){if (x==null){return;}//先找到左子节点if (x.left!=null){//如果左子节点不为空 则递归遍历左子节点preErgodic(x.left,key);}if (x.right!=null){preErgodic(x.right,key);}key.inQueue(x.key);}
4.层序遍历:

层序遍历,就是从根节点(第一层)开始,依次向下,获取每一层所有结点的值。

以该树为例,那么层序遍历结果是:

10-2-12-1-8-11-16-5-9-3-6-4

实现思路:

  1. 创建一个队列,存储每一层的节点;
  2. 使用循环队列中弹出一个节点;
  3. 然后获取到到当前节点key
  4. 如果当前节点的左子节点不为空,则把左子结点放入队列中
  5. 如果当前节点的右子节点不为空,则把右子结点放入队列中

代码:

  public Queue<Key> layerErgodic(){Queue<Key> keys=new Queue<>();   //存储遍历结果队列Queue<TreeNode> nodes=new Queue<>();//循环节点队列nodes.inQueue(root); //将根节点添加至循环队列中while (!nodes.isEmpty()){ //如果不为空 则代表还需要判断是否有 子节点判断TreeNode treeNode = nodes.outQueue();keys.inQueue(treeNode.key); //先将该节点加入 结果队列中if (treeNode.left!=null){nodes.inQueue(treeNode.left);}if (treeNode.right!=null){nodes.inQueue(treeNode.right);}}return keys;}//运行结果:
10-2-12-1-8-11-16-5-9-3-6-4-

实际例题:

在力扣的题中,有时候是要求你将每一层作为一个结果输出,比单纯输出顺序要更为复杂一点点。

思路:通过递归的方式+两个队列来实现.

首先将根节点传入父层节点队列,然后检查根节点的左右子节点,将左右子结点添加到子层待搜索队列,父层节点中的所有队列元素取出后,将待搜索的子结点队列作为父节点队列进行递归。然后将每一层的父节点队列作为结果添加即可。

第一层递归。

第二层递归

完整代码:

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {List<List<Integer>> result=new ArrayList<>();public List<List<Integer>> levelOrder(TreeNode root) {//层序遍历 就是广度优先搜索//创建待搜索队列if(root==null){return result;}Queue<TreeNode> queue=new LinkedList<>();queue.offer(root);cenxu(queue);return result;}public void cenxu(Queue queue){ //将根节点和队列传入//将当前节点传入queueList<Integer> r=new ArrayList<>();  //层序结果Queue<TreeNode> waitSearch=new LinkedList<>();//通过两个队列来实现 父队列存放当前层的所有节点 子队列存当前节点的所有子结点while(!queue.isEmpty()){//遍历父节点//先取出所有节点 然后表示是一个层的//存放到结果中TreeNode node=(TreeNode)queue.poll();r.add(node.val);if(node.left!=null){//将当前层级的所有子结点存入 子队列中waitSearch.offer(node.left);}if(node.right!=null){waitSearch.offer(node.right);}}//递归 队列就是下一个的父队列result.add(r);if(waitSearch.isEmpty()){return;}cenxu(waitSearch);}
}

相关文章:

数据结构:树

树的基本定义&#xff1a; 树是一种数据结构&#xff0c;它是由n&#xff08;n>1&#xff09;个有限节点组成一个具有层次关系的集合。把它叫做 “树” 是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。它具有以下的特点&#xff1a; …...

矩阵sum,prod函数

s u m sum sum表示求和, p r o d prod prod表示求乘积 s u m sum sum函数 对于矩阵&#xff0c;可以对某一行或某一列求和&#xff0c;也可以对矩阵整体求和 s u m ( a , 1 ) sum(a,1) sum(a,1)计算每一列的和 s u m ( a , 2 ) sum(a,2) sum(a,2)计算每一行的和 计算矩阵整体…...

Cursor安装与使用,5分钟完成需求

Cursor简单介绍 Cursor是一款基于AI的代码编辑器&#xff0c;旨在帮助开发者更高效地编写和管理代码。它提供了智能代码补全、AI对话和跨文件编辑等创新功能。 一、安装下载 1、下载cursor&#xff1a;https://www.cursor.com/ 2、注册账号&#xff0c;直接拿自己的邮箱登录…...

嵌入式系统应用-LVGL的应用-平衡球游戏 part1

平衡球游戏 part1 1 平衡球游戏的界面设计2 界面设计2.1 背景设计2.2 球的设计2.3 移动球的坐标2.4 用鼠标移动这个球2.5 增加边框规则2.6 效果图 3 为小球增加增加动画效果3.1 增加移动效果代码3.2 具体效果图片 平衡球游戏 part2 第二部分文章在这里 1 平衡球游戏的界面设计…...

Vue基本语法

Options API 选项式/配置式api 需要在script中的export default一个对象对象中可以包含data、method、components等keydata是数据&#xff0c;数据必须是一个方法&#xff08;如果是对象&#xff0c;会导致多组件的时候&#xff0c;数据互相影响&#xff0c;因为对象赋值后&…...

UIE与ERNIE-Layout:智能视频问答任务初探

内容来自百度飞桨ai社区UIE与ERNIE-Layout&#xff1a;智能视频问答任务初探&#xff1a; 如有侵权&#xff0c;请联系删除 1 环境准备 In [2] # 安装依赖库 !pip install paddlenlp --upgrade !pip install paddleocr --upgrade !pip install paddlespeech --upgrade In …...

Mac启动服务慢问题解决,InetAddress.getLocalHost().getHostAddress()慢问题。

项目启动5分钟&#xff0c;很明显有问题。像网上其他的提高jvm参数就不说了&#xff0c;应该不是这个问题&#xff0c;也就快一点。 首先找到自己的电脑名称&#xff08;用命令行也行&#xff0c;只要能找到自己电脑名称就行&#xff0c;这里直接在共享里看&#xff09;。 复制…...

Django 视图层

from django.shortcuts import render, HttpResponse, redirectfrom django.http import JsonResponse1. render: 渲染模板 def index(request):print(reverse(index))return render(request, "index.html")return render(request, index.html, context{name: lisi})…...

HickWall 详解

优质博文&#xff1a;IT-BLOG-CN 一、监控分类 【1】Tracing调用链&#xff1a; 【2】Logging日志&#xff1a; 【3】Metrics指标&#xff1a;在应用发布之后&#xff0c;会长时间存在的度量维度。某个接口的请求量、响应时间。 Metrics数据模型 二、Metirc 接入 【1】pom…...

开源的跨平台SQL 编辑器Beekeeper Studio

一款开源的跨平台 SQL 编辑器&#xff0c;提供 SQL 语法高亮、自动补全、数据表内容筛选与过滤、连接 Web 数据库、存储历史查询记录等功能。该编辑器支持 SQLite、MySQL、MariaDB、Postgres 等主流数据库&#xff0c;并兼容 Windows、macOS、Linux 等桌面操作系统。 项目地址…...

Linux应用层学习——Day4(进程处理)

system #include<stdio.h> #include<stdlib.h>int main(int argc, char const *argv[]) {//使用标准库函数创建子进程//int system (const char *__command);//const char *__command:使用linux命令直接创建一个子进程//return:成功返回0 失败返回失败编号int sys…...

起别名typedef

#include<stdio.h> //typedef int myType1; //typedef char myType2; typedef struct { int a; int b; }po; int main() { /*myType1 a5; myType2 bo; printf("%d\n",a); printf("%c\n",b);*/ po p;//不需要加struct关键…...

【Linux内核】ashmem pin/unpin

前言 在 Linux 内核的 ASHMEM&#xff08;Android Shared Memory&#xff09;实现中&#xff0c;pin 和 unpin 操作主要用于管理共享内存的生命周期和可用性。这些操作有助于确保在内存使用期间&#xff0c;特定的共享内存区域不会被回收或释放。 Pin 操作 定义 Pin 操作用…...

【docker】docker网络六种网络模式

Docker 网络模式总结 网络模式描述使用场景bridge默认的网络模式&#xff0c;容器之间通过虚拟网桥通信&#xff0c;容器与宿主机隔离。单机部署、本地开发、小型项目host容器与宿主机共享网络堆栈&#xff0c;容器直接使用宿主机的 IP 地址。高性能网络应用、日志处理、大量与…...

永磁同步电机谐波抑制算法(11)——基于矢量比例积分调节器(vector PI controller,VPI controller)的谐波抑制策略

1.前言 相比于传统的谐振调节器&#xff0c;矢量比例积分调节器&#xff08;vector PI controller&#xff0c;VPI controller&#xff09;多一个可调零点&#xff0c;能够实现电机模型的零极点对消。因此VPI调节器也被广泛应用于交流控制/谐波抑制中。 2.参考文献 [1] A. G…...

排序算法中稳定性的意义和作用

多关键字排序&#xff1a;当需要对数据进行多个关键字排序时&#xff0c;稳定性变得非常重要。例如&#xff0c;先按次要关键字排序&#xff0c;再按主要关键字排序。如果排序算法是稳定的&#xff0c;那么在按主要关键字排序后&#xff0c;次要关键字的顺序将被保留。保持关联…...

网站怎么防御https攻击

HTTPS攻击&#xff0c;它不仅威胁到网站的数据安全&#xff0c;还可能影响用户隐私和业务稳定运行。 HTTPS攻击主要分为以下几种类型&#xff1a; 1.SSL劫持&#xff1a;攻击者通过中间人攻击手段&#xff0c;篡改HTTPS流量&#xff0c;从而实现对数据的窃取或伪造。 2.中间人攻…...

gitignore 不起作用

.gitignore不起作用 文件已提交至远程仓库&#xff0c;已经被Git跟踪。清除缓存.gitignore位置可能不是与 .git隐藏文件夹同级目录。将文件移至同级目录缓存未清除 清除缓存 清楚git缓存步骤 进入项目路径 清除本地当前的Git缓存 git rm -r --cached . 应用.gitignore等本地…...

Hive学习基本概念

基本概念 hive是什么&#xff1f; Facebook 开源&#xff0c;用于解决海量结构化日志的数据统计。 基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张表&#xff0c;并提供类SQL查询功能 本质是将HQL转化为MapReduce程序。 Hive处理的数据存储在H…...

在 Ubuntu 使用 fonts-noto-cjk 设置 Matplotlib 支持中文的完整教程

在 Ubuntu 使用 fonts-noto-cjk 设置 Matplotlib 支持中文的完整教程 1. 为什么需要配置中文字体&#xff1f;2. 安装 fonts-noto-cjk安装命令&#xff1a;检查字体安装是否成功 3. 配置 Matplotlib 支持中文3.1 手动加载字体3.2 设置全局字体&#xff08;可选&#xff09;修改…...

《C++ Primer Plus》学习笔记|第10章 对象和类 (24-12-2更新)

文章目录 10.3 类的构造函数和析构函数10.3.2 使用构造函数显式地调用构造函数隐式地调用构造函数使用对象指针 10.3.3默认构造函数10.3.4 析构函数析构函数示例 10.4 this指针三个const的作用 10.5 对象数组10.6 类作用域10.9 复习题1.什么是类&#xff1f;2.类如何实现抽象、…...

SpringMVC接收数据

一、访问路径设置: RequestMapping注解的作用就是将请求的URL地址和处理请求的方式(handler方法)关联起来&#xff0c;建立映射关系;SpringMVC接收到指定的请求&#xff0c;就会来找到在映射关系中对应的方法来处理这个请求 1.精准路径匹配: 在RequestMapping注解指定URL地址…...

Python数组拆分(array_split())

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…...

Git 使用总结

下载 git bash&#xff1a;http://git-scm.com/download/win 第一次使用 git 时&#xff0c;配置用户信息&#xff1a; git config --global user.email "your.emailexample.com" 从github仓库中下载项目到本地&#xff0c;修改后重新上传&#xff1a; git clone 项…...

NaviveUI框架的使用 ——安装与引入(图标安装与引入)

文章目录 概述安装直接引入引入图标样式库 概述 &#x1f349;Naive UI 是一个轻量、现代化且易于使用的 Vue 3 UI 组件库&#xff0c;它提供了一组简洁、易用且功能强大的组件&#xff0c;旨在为开发者提供更高效的开发体验&#xff0c;特别是对于构建现代化的 web 应用程序。…...

YOLOv11 NCNN安卓部署

YOLOv11 NCNN安卓部署 之前自己在验证更换relu激活函数重新训练部署模型的时候&#xff0c;在使用ncnn代码推理验证效果很好&#xff0c;但是部署到安卓上cpu模式会出现大量的错误检测框&#xff0c;现已更换会官方默认的权重 前言 YOLOv11 NCNN安卓部署 目前的帧率可以稳定…...

多线程安全单例模式的传统解决方案与现代方法

在多线程环境中实现安全的单例模式时&#xff0c;传统的双重检查锁&#xff08;Double-Checked Locking&#xff09;方案和新型的std::once_flag与std::call_once机制是两种常见的实现方法。它们在实现机制、安全性和性能上有所不同。 1. 传统的双重检查锁方案 双重检查锁&am…...

golang debug调试

1. 本地调试 1&#xff1a;Add Configurations 添加配置文件&#xff08;Run kind &#xff1a;Directory&#xff09; 2&#xff1a;进入run运行窗口 3&#xff1a;debug断点调试模式 1. Resume Program (继续运行) 图标: ▶️ 或 ► 快捷键: F9&#xff08;Windows/Linux&a…...

安装 RabbitMQ 服务

安装 RabbitMQ 服务 一. RabbitMQ 需要依赖 Erlang/OTP 环境 (1) 先去 RabbitMQ 官网&#xff0c;查看 RabbitMQ 需要的 Erlang 支持&#xff1a;https://www.rabbitmq.com/ 进入官网&#xff0c;在 Docs -> Install and Upgrade -> Erlang Version Requirements (2) …...

pandas 大数据获取某列所有唯一值

目录 方法1: 方法2: 方法3 处理大数据: 方法1: data.groupby().groups.keys() import pandas as pd# 假设我们有以下的数据 data = {RTDR_name: [A, B, A, C, B, A],value: [1, 2, 3, 4, 5, 6] }# 创建 DataFrame temp_data = pd.DataFrame(data)# 获取 RTDR_name 列的…...

【AI系统】LLVM 架构设计和原理

LLVM 架构设计和原理 在上一篇文章中&#xff0c;我们详细探讨了 GCC 的编译过程和原理。然而&#xff0c;由于 GCC 存在代码耦合度高、难以进行独立操作以及庞大的代码量等缺点。正是由于对这些问题的意识&#xff0c;人们开始期待新一代编译器的出现。在本节&#xff0c;我们…...

Node.js 中的文件系统(fs)模块详解与代码示例

Node.js 中的文件系统&#xff08;fs&#xff09;模块详解与代码示例 Node.js 的 fs 模块提供了与文件系统交互的能力&#xff0c;包括文件的读写、目录的管理等。以下是 fs 模块中一些常用方法的详细解释和代码示例&#xff1a; 1. 异步读取文件内容 作用&#xff1a;异步读…...

TinyXML2的一些用法

TinyXML2 原始字符串字面量 TinyXML21. XML文档操作1.1 LoadFile(const char* filename)1.2SaveFile(const char* filename)1.3RootElement()1.4Parse(const char* xml) 2.元素操作2.1 FirstChildElement(const char* name nullptr)2.2 NextSiblingElement(const char* name …...

【Vue3】从零开始创建一个VUE项目

【Vue3】从零开始创建一个VUE项目 手动创建VUE项目附录 package.json文件报错处理: Failed to get response from https://registry.npmjs.org/vue-cli-version-marker 相关链接&#xff1a; 【VUE3】【Naive UI】&#xff1c;NCard&#xff1e; 标签 【VUE3】【Naive UI】&…...

springboot370高校宣讲会管理系统(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 高校宣讲会管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c…...

navicat连接mysql 8.0以上版本2059错误

安装了最新版本8.0.4的mysql之后&#xff0c;使用navicat链接提示以下错误。原因是因为mysql8.0 之前的版本中加密规则是 mysql_native_password&#xff0c;而 mysql8.0 之后的版本加密规则是caching_sha2_password 处理方案 解决方案1&#xff1a;下载安装最新版本navicat…...

SQL优化与性能——C++与SQL性能优化

在开发高效的数据库应用程序时&#xff0c;性能优化至关重要&#xff0c;尤其是当系统规模逐渐扩大或并发请求增加时。数据库操作往往是应用程序性能的瓶颈所在&#xff0c;因此&#xff0c;在 C 应用程序中合理优化数据库操作&#xff0c;管理数据库连接池、使用批量插入与更新…...

AI高中数学教学视频生成技术:利用通义千问、MathGPT、视频多模态大模型,语音大模型,将4个模型融合 ,生成高中数学教学视频,并给出实施方案。

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下AI高中数学教学视频生成技术&#xff1a;利用通义千问、MathGPT、视频多模态大模型&#xff0c;语音大模型&#xff0c;将4个模型融合 &#xff0c;生成高中数学教学视频&#xff0c;并给出实施方案。本文利用专家模…...

vscode远程连接ssh

一. 使用vscode里的ssh查件连不上远程的解决方法 删除Windows上的known_host文件&#xff0c;该文件会在连接之后自动生成&#xff0c;用于验证远程服务器的身份。 konwn_host和id_rsa&#xff0c;id_rsa.pub的关系 &#xff08;1&#xff09;konwn_host用于客户端验证远程服务…...

学习ASP.NET Core的身份认证(基于Session的身份认证2)

基于Session的身份认证通过后&#xff0c;后续访问控制器的函数时该如何控制访问权限&#xff1f;虽然可以按上篇文章方式在需要做控制的函数开头检查Session的用户标识&#xff0c;可以写个全局通用检查类供所需函数调用&#xff0c;但还是有更简便的方法&#xff0c;本文学习…...

深度学习基本单元结构与输入输出维度解析

深度学习基本单元结构与输入输出维度解析 在深度学习领域&#xff0c;模型的设计和结构是理解其性能和应用的关键。本文将介绍深度学习中的基本单元结构&#xff0c;包括卷积神经网络&#xff08;CNN&#xff09;、反卷积&#xff08;转置卷积&#xff09;、循环神经网络&…...

playwright 学习复仇记-1 开端

前言 说到 web 自动化&#xff0c;大家最熟悉的就是 selenium 了&#xff0c;selenium 之后又出现了三个强势的框架Puppeteer、CyPress、TestCafe&#xff0c; 但这3个都需要掌握 JavaScript 语言&#xff0c;所以只是少部分人在用。 2020年微软开源一个 UI 自动化测试工具 Pl…...

从零开始使用GOT-OCR2.0——多模态OCR项目:微调数据集构建 + 训练(解决训练报错,成功实验微调训练)

在上一篇文章记录了GOT-OCR项目的环境配置和基于官方模型参数的基础使用。环境安装的博文快速链接&#xff1a; 从零开始使用GOT-OCR2.0——多模态通用型OCR&#xff08;非常具有潜力的开源OCR项目&#xff09;&#xff1a;项目环境安装配置 测试使用-CSDN博客 本章在环境配置…...

Rust学习笔记_10——守卫

Rust学习笔记_07——枚举和范围 Rust学习笔记_08——String Rust学习笔记_09——模式匹配 守卫 文章目录 守卫1. 介绍2. 基本用法3. 示例4. 复杂用法5. if let5.1 基本用法5.2 示例5.3 守卫与if let的区别与联系 1. 介绍 在Rust中&#xff0c;守卫&#xff08;guard&#xff…...

UE5 打包报错 Unknown structure 的解决方法

在虚幻引擎5.5 打包报错如下&#xff1a; UATHelper: 打包 (Windows): LogInit: Display: LogProperty: Error: FStructProperty::Serialize Loading: Property ‘StructProperty /Game/Components/HitReactionComponent/Blueprints/BI_ReactionInterface.BI_ReactionInterface…...

如何打开链接中的网址

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了包管理相关的内容,本章回中将介绍如何使用url_launcher包.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里介绍url_launcher包主要用来打开Url中的内容,Url可以是电话号码,网址,邮箱等内容。如…...

React 前端框架4

六、React 中的事件处理 &#xff08;一&#xff09;绑定事件的方式 在 React 中&#xff0c;事件绑定和传统的 HTML 中的事件绑定有一些不同&#xff0c;它采用了驼峰命名法来命名事件名称&#xff0c;并且事件绑定的属性值是一个函数。例如&#xff0c;在 HTML 中绑定点击事…...

Neo4j启动时指定JDK版本

项目使用jdk1.8&#xff0c;同时需要安装neo4j5.15版本&#xff0c;使用jdk17. 1.mac或者liunx&#xff0c;找到neo4j目录bin的下neo4j文件 设置JAVA_HOME: 2.windows,找到bin下面的neo4j.bat文件 set "JAVA_HOME{JDK文件目录}" 重启后生效。...

【k8s深入理解之 Scheme 补充-2】理解 register.go 暴露的 AddToScheme 函数

AddToScheme 函数 AddToScheme 就是为了对外暴露&#xff0c;方便别人调用&#xff0c;将当前Group组的信息注册到其 Scheme 中&#xff0c;以便了解该 Group 组的数据结构&#xff0c;用于后续处理 项目版本用途使用场景k8s.io/apiV1注册资源某一外部版本数据结构&#xff0…...

TextBlob:简单高效的自然语言处理工具

TextBlob&#xff1a;简单高效的自然语言处理工具 TextBlob 是一个基于 NLTK 和 Pattern 的自然语言处理库&#xff0c;以简单易用著称。它提供了直观的 API&#xff0c;支持文本分析、情感分析、拼写纠正等常见任务&#xff0c;非常适合快速原型开发和学习。 为什么选择 Text…...