B、B+、红黑树、AVL树的对比

news2024/11/20 8:28:24

主要来自 小林coding https://mp.weixin.qq.com/s/AoPq8poENF9T4mVS1fDFPw#
在这里插入图片描述

怎样的索引的数据结构是好的?

MySQL 的数据是持久化的,意味着数据(索引+记录)是保存到磁盘上的,因为这样即使设备断电了,数据也不会丢失。

磁盘是一个慢的离谱的存储设备,有多离谱呢?

人家内存的访问速度是纳秒级别的,而磁盘访问的速度是毫秒级别的,也就是说读取同样大小的数据,磁盘中读取的速度比从内存中读取的速度要慢上万倍,甚至几十万倍。

磁盘读写的最小单位是扇区,扇区的大小只有 512B 大小,操作系统一次会读写多个扇区,所以操作系统的最小读写单位是块(Block)。Linux 中的块大小为 4KB,也就是一次磁盘 I/O 操作会直接读写 8 个扇区。

由于数据库的索引是保存到磁盘上的,因此当我们通过索引查找某行数据的时候,就需要先从磁盘读取索引到内存,再通过索引从磁盘中找到某行数据,然后读入到内存,也就是说查询过程中会发生多次磁盘 I/O,而磁盘 I/O 次数越多,所消耗的时间也就越大。

所以,我们希望索引的数据结构能在尽可能少的磁盘的 I/O 操作中完成查询工作,因为磁盘 I/O 操作越少,所消耗的时间也就越小。

另外,MySQL 是支持范围查找的,所以索引的数据结构不仅要能高效地查询某一个记录,而且也要能高效地执行范围查找。

所以,要设计一个适合 MySQL 索引的数据结构,至少满足以下要求:

  • 能在尽可能少的磁盘的 I/O 操作中完成查询工作;
  • 要能高效地查询某一个记录,也要能高效地执行范围查找;

分析完要求后,我们针对每一个数据结构分析一下。

二分查找数组

在这里插入图片描述
可以看到,二分查找法每次都把查询的范围减半,这样时间复杂度就降到了 O(logn),但是每次查找都需要不断计算中间位置。

二分查找树

用数组来实现线性排序的数据虽然简单好用,但是插入新元素的时候性能太低。

因为插入一个元素,需要将这个元素之后的所有元素后移一位,如果这个操作发生在磁盘中呢?这必然是灾难性的。因为磁盘的速度比内存慢几十万倍,所以我们不能用一种线性结构将磁盘排序。

其次,有序的数组在使用二分查找的时候,每次查找都要不断计算中间的位置。

那我们能不能设计一个非线形且天然适合二分查找的数据结构呢?

有的,请看下图这个神奇的操作,找到所有二分查找中用到的所有中间节点,把他们用指针连起来,并将最中间的节点作为根节点。
在这里插入图片描述

怎么样?是不是变成了二叉树,不过它不是普通的二叉树,它是一个二叉查找树。

二叉查找树的特点是一个节点的左子树的所有节点都小于这个节点,右子树的所有节点都大于这个节点,这样我们在查询数据时,不需要计算中间节点的位置了,只需将查找的数据与节点的数据进行比较。

假设,我们查找索引值为 key 的节点:

  1. 如果 key 大于根节点,则在右子树中进行查找;

  2. 如果 key 小于根节点,则在左子树中进行查找;

  3. 如果 key 等于根节点,也就是找到了这个节点,返回根节点即可。

二叉查找树查找某个节点的动图演示如下,比如要查找节点 3
在这里插入图片描述
另外,二叉查找树解决了插入新节点的问题,因为二叉查找树是一个跳跃结构,不必连续排列。这样在插入的时候,新节点可以放在任何位置,不会像线性结构那样插入一个元素,所有元素都需要向后排列。

下面是二叉查找树插入某个节点的动图演示:
在这里插入图片描述
因此,二叉查找树解决了连续结构插入新元素开销很大的问题,同时又保持着天然的二分结构。

那是不是二叉查找树就可以作为索引的数据结构了呢?

不行不行,二叉查找树存在一个极端情况,会导致它变成一个瘸子!

当每次插入的元素都是二叉查找树中最大的元素,二叉查找树就会退化成了一条链表,查找数据的时间复杂度变成了 O(n),如下动图演示:
在这里插入图片描述
由于树是存储在磁盘中的,访问每个节点,都对应一次磁盘 I/O 操作(假设一个节点的大小「小于」操作系统的最小读写单位块的大小),也就是说树的高度就等于每次查询数据时磁盘 IO 操作的次数,所以树的高度越高,就会影响查询性能。

二叉查找树由于存在退化成链表的可能性,会使得查询操作的时间复杂度从 O(logn)降低为 O(n)。

而且会随着插入的元素越多,树的高度也变高,意味着需要磁盘 IO 操作的次数就越多,这样导致查询性能严重下降,再加上不能范围查询,所以不适合作为数据库的索引结构。

什么是AVL自平衡二叉树?

为了解决二叉查找树会在极端情况下退化成链表的问题,后面就有人提出平衡二叉查找树(AVL 树)。

主要是在二叉查找树的基础上增加了一些条件约束:每个节点的左子树和右子树的高度差不能超过 1。也就是说节点的左子树和右子树仍然为平衡二叉树,这样查询操作的时间复杂度就会一直维持在 O(logn) 。

下图是每次插入的元素都是平衡二叉查找树中最大的元素,可以看到,它会维持自平衡:
在这里插入图片描述
除了平衡二叉查找树,还有很多自平衡的二叉树,比如红黑树,它也是通过一些约束条件来达到自平衡,不过红黑树的约束条件比较复杂,不是本篇的重点重点,大家可以看《数据结构》相关的书籍来了解红黑树的约束条件。

下面是红黑树插入节点的过程,这左旋右旋的操作,就是为了自平衡。
在这里插入图片描述
不管平衡二叉查找树还是红黑树,都会随着插入的元素增多,而导致树的高度变高,这就意味着磁盘 I/O 操作次数多,会影响整体数据查询的效率。

比如,下面这个平衡二叉查找树的高度为 5,那么在访问最底部的节点时,就需要磁盘 5 次 I/O 操作。

在这里插入图片描述
根本原因是因为它们都是二叉树,也就是每个节点只能保存 2 个子节点 ,如果我们把二叉树改成 M 叉树(M>2)呢?

比如,当 M=3 时,在同样的节点个数情况下,三叉树比二叉树的树高要矮。

在这里插入图片描述

因此,当树的节点越多的时候,并且树的分叉数 M 越大的时候,M 叉树的高度会远小于二叉树的高度。

什么是 B 树

自平衡二叉树虽然能保持查询操作的时间复杂度在O(logn),但是因为它本质上是一个二叉树,每个节点只能有 2 个子节点,那么当节点个数越多的时候,树的高度也会相应变高,这样就会增加磁盘的 I/O 次数,从而影响数据查询的效率。

为了解决降低树的高度的问题,后面就出来了 B 树,它不再限制一个节点就只能有 2 个子节点,而是允许 M 个子节点 (M>2),从而降低树的高度。

B 树的每一个节点最多可以包括 M 个子节点,M 称为 B 树的阶,所以 B 树就是一个多叉树。

假设 M = 3,那么就是一棵 3 阶的 B 树,特点就是每个节点最多有 2 个(M-1个)数据和最多有 3 个(M个)子节点,超过这些要求的话,就会分裂节点,比如下面的的动图:
在这里插入图片描述
我们来看看一棵 3 阶的 B 树的查询过程是怎样的?

在这里插入图片描述

假设我们在上图一棵 3 阶的 B 树中要查找的索引值是 9 的记录那么步骤可以分为以下几步:

  1. 与根节点的索引(4,8)进行比较,9 大于 8,那么往右边的子节点走;
  2. 然后该子节点的索引为(10,12),因为 9 小于 10,所以会往该节点的左边子节点走;
  3. 走到索引为9的节点,然后我们找到了索引值 9 的节点。

可以看到,一棵 3 阶的 B 树在查询叶子节点中的数据时,由于树的高度是 3 ,所以在查询过程中会发生 3 次磁盘 I/O 操作。

而如果同样的节点数量在平衡二叉树的场景下,树的高度就会很高,意味着磁盘 I/O 操作会更多。所以,B 树在数据查询中比平衡二叉树效率要高。

但是 B 树的每个节点都包含数据(索引+记录),而用户的记录数据的大小很有可能远远超过了索引数据,这就需要花费更多的磁盘 I/O 操作次数来读到「有用的索引数据」。

而且,在我们查询位于底层的某个节点(比如 A 记录)过程中,「非 A 记录节点」里的记录数据会从磁盘加载到内存,但是这些记录数据是没用的,我们只是想读取这些节点的索引数据来做比较查询,而「非 A 记录节点」里的记录数据对我们是没用的,这样不仅增多磁盘 I/O 操作次数,也占用内存资源。

另外,如果使用 B 树来做范围查询的话,需要使用中序遍历,这会涉及多个节点的磁盘 I/O 问题,从而导致整体速度下降。

什么是 B+ 树?

B+ 树就是对 B 树做了一个升级,MySQL 中索引的数据结构就是采用了 B+ 树,B+ 树结构如下图:

在这里插入图片描述

B+ 树与 B 树差异的点,主要是以下这几点:

  • 叶子节点(最底部的节点)才会存放实际数据(索引+记录),非叶子节点只会存放索引;
  • 所有索引都会在叶子节点出现,叶子节点之间构成一个有序链表;
  • 非叶子节点的索引也会同时存在在子节点中,并且是在子节点中所有索引的最大(或最小)。

非叶子节点中有多少个子节点,就有多少个索引;

下面通过三个方面,比较下 B+ 和 B 树的性能区别。

1、单点查询

B 树进行单个索引查询时,最快可以在 O(1) 的时间代价内就查到,而从平均时间代价来看,会比 B+ 树稍快一些。

但是 B 树的查询波动会比较大,因为每个节点即存索引又存记录,所以有时候访问到了非叶子节点就可以找到索引,而有时需要访问到叶子节点才能找到索引。

B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比存储即存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O次数会更少。

2、插入和删除效率

B+ 树有大量的冗余节点,这样使得删除一个节点的时候,可以直接从叶子节点中删除,甚至可以不动非叶子节点,这样删除非常快,

比如下面这个动图是删除 B+ 树某个叶子节点节点的过程:
在这里插入图片描述
注意,:B+ 树对于非叶子节点的子节点和索引的个数,定义方式可能会有不同,有的是说非叶子节点的子节点的个数为 M 阶,而索引的个数为 M-1(这个是维基百科里的定义),因此我本文关于 B+ 树的动图都是基于这个。但是我在前面介绍 B+ 树与 B+ 树的差异时,说的是「非叶子节点中有多少个子节点,就有多少个索引」,主要是 MySQL 用到的 B+ 树就是这个特性。

甚至,B+ 树在删除根节点的时候,由于存在冗余的节点,所以不会发生复杂的树的变形,比如下面这个动图是删除 B+ 树根节点的过程:

在这里插入图片描述
B 树则不同,B 树没有冗余节点,删除节点的时候非常复杂,比如删除根节点中的数据,可能涉及复杂的树的变形,比如下面这个动图是删除 B 树根节点的过程:
在这里插入图片描述

B+ 树的插入也是一样,有冗余节点,插入可能存在节点的分裂(如果节点饱和),但是最多只涉及树的一条路径。而且 B+ 树会自动平衡,不需要像更多复杂的算法,类似红黑树的旋转操作等。

因此,B+ 树的插入和删除效率更高。

3、范围查询

B 树和 B+ 树等值查询原理基本一致,先从根节点查找,然后对比目标数据的范围,最后递归的进入子节点查找。

因为 B+ 树所有叶子节点间还有一个链表进行连接,这种设计对范围查找非常有帮助,比如说我们想知道 12 月 1 日和 12 月 12 日之间的订单,这个时候可以先查找到 12 月 1 日所在的叶子节点,然后利用链表向右遍历,直到找到 12 月12 日的节点,这样就不需要从根节点查询了,进一步节省查询需要的时间。

而 B 树没有将所有叶子节点用链表串联起来的结构,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。

因此,存在大量范围检索的场景,适合使用 B+树,比如数据库。而对于大量的单个索引查询的场景,可以考虑 B 树,比如 nosql 的MongoDB。

MySQL 中的 B+ 树

MySQL 的存储方式根据存储引擎的不同而不同,我们最常用的就是 Innodb 存储引擎,它就是采用了 B+ 树作为了索引的数据结构。

下图就是 Innodb 里的 B+ 树:
在这里插入图片描述
但是 Innodb 使用的 B+ 树有一些特别的点,比如:

B+ 树的叶子节点之间是用「双向链表」进行连接,这样的好处是既能向右遍历,也能向左遍历。

B+ 树点节点内容是数据页,数据页里存放了用户的记录以及各种信息,每个数据页默认大小是 16 KB。

Innodb 根据索引类型不同,分为聚集和二级索引。他们区别在于,聚集索引的叶子节点存放的是实际数据,所有完整的用户记录都存放在聚集索引的叶子节点,而二级索引的叶子节点存放的是主键值,而不是实际数据。

因为表的数据都是存放在聚集索引的叶子节点里,所以 InnoDB 存储引擎一定会为表创建一个聚集索引,且由于数据在物理上只会保存一份,所以聚簇索引只能有一个,而二级索引可以创建多个。

更多关于 Innodb 的 B+ 树,可以看我之前写的这篇:从数据页的角度看 B+ 树。

总结
MySQL 是会将数据持久化在硬盘,而存储功能是由 MySQL 存储引擎实现的,所以讨论 MySQL 使用哪种数据结构作为索引,实际上是在讨论存储引使用哪种数据结构作为索引,InnoDB 是 MySQL 默认的存储引擎,它就是采用了 B+ 树作为索引的数据结构。

要设计一个 MySQL 的索引数据结构,不仅仅考虑数据结构增删改的时间复杂度,更重要的是要考虑磁盘 I/0 的操作次数。因为索引和记录都是存放在硬盘,硬盘是一个非常慢的存储设备,我们在查询数据的时候,最好能在尽可能少的磁盘 I/0 的操作次数内完成。

二分查找树虽然是一个天然的二分结构,能很好的利用二分查找快速定位数据,但是它存在一种极端的情况,每当插入的元素都是树内最大的元素,就会导致二分查找树退化成一个链表,此时查询复杂度就会从 O(logn)降低为 O(n)。

为了解决二分查找树退化成链表的问题,就出现了自平衡二叉树,保证了查询操作的时间复杂度就会一直维持在 O(logn) 。但是它本质上还是一个二叉树,每个节点只能有 2 个子节点,随着元素的增多,树的高度会越来越高。

而树的高度决定于磁盘 I/O 操作的次数,因为树是存储在磁盘中的,访问每个节点,都对应一次磁盘 I/O 操作,也就是说树的高度就等于每次查询数据时磁盘 IO 操作的次数,所以树的高度越高,就会影响查询性能。

B 树和 B+ 都是通过多叉树的方式,会将树的高度变矮,所以这两个数据结构非常适合检索存于磁盘中的数据。

但是 MySQL 默认的存储引擎 InnoDB 采用的是 B+ 作为索引的数据结构,原因有:

B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比存储即存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O次数会更少。

B+ 树有大量的冗余节点(所有非叶子节点都是冗余索引),这些冗余索引让 B+ 树在插入、删除的效率都更高,比如删除根节点的时候,不会像 B 树那样会发生复杂的树的变化;

B+ 树叶子节点之间用链表连接了起来,有利于范围查询,而 B 树要实现范围查询,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。

完!

B + 树与红黑树的比较

红黑树等平衡树也可以用来实现索引,但是文件系统及数据库系统普遍采用 B+ Tree 作为索引结构,主要有以下两个原因:

(一)磁盘 IO 次数

B+ 树一个节点可以存储多个元素,相对于红黑树的树高更低,磁盘 IO 次数更少。

(二)磁盘预读特性

为了减少磁盘 I/O 操作,磁盘往往不是严格按需读取,而是每次都会预读。预读过程中,磁盘进行顺序读取,顺序读取不需要进行磁盘寻道。每次会读取页的整数倍。

操作系统一般将内存和磁盘分割成固定大小的块,每一块称为一页,内存与磁盘以页为单位交换数据。数据库系统将索引的一个节点的大小设置为页的大小,使得一次 I/O 就能完全载入一个节点。

B + 树与 B 树的比较
B+ 树的磁盘 IO 更低

B+ 树的内部节点并没有指向关键字具体信息的指针。因此其内部节点相对 B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。

B+ 树的查询效率更加稳定

由于非叶子结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

B+ 树元素遍历效率高

B 树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。正是为了解决这个问题,B+树应运而生。B+树只要遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而 B 树不支持这样的操作(或者说效率太低)。

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

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

相关文章

SpringBoot自动配置原理解析

​ SpringBoot的主旨是约定大于配置,开发项目初期阶段,我们不需要做过多的配置,SpringBoot已经帮我们自动配置好了大部分的内容,比如仲裁依赖机制,自动引入需要的依赖,自动配置等内容。让我们能够将更多的精…

2023年6款程序员常用IDE工具推荐

IDE是“集成开发环境”的缩写,是一种软件应用程序,旨在为程序员提供一个集成的工作环境,使他们可以编写、测试和调试代码,同时提供各种辅助工具,以提高开发效率和质量。 通常包含了一个代码编辑器,能够在代…

AI ChatGpt使用工具

1、OpenAi 这个使用注册和使用成本比较高,新手不建议;有钱滤过,想使用最新的模型的滤过; 1.1、准备工作 能访问外网;(本链接不提供)准备一个国外手机号,用于接受注册验证码&#xf…

数据结构——结构体 内存对齐

在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员&#xff…

试用「ChatGPT」几周之后

冷静下来,不吹不黑。 01 最近半年,互联网一款现象级的应用诞生:「ChatGPT」; 其火爆的程度,不输前面的羊了个羊; 最初了解到ChatGPT还是春节的时候,但那时网上的测评还没引起足够的好奇心&…

美女诱惑来袭,你抖的过嘛~python下载

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 我又又又来采集美女小姐姐了 兜兜转转还是小姐姐得我心吖~ 哈哈哈哈哈哈哈哈哈哈 目录&#xff08;想看哪里点哪里 &#x1f61d;&#xff09; 前言开发环境:思路流程: <固定公式>代码展示尾语 开发环境: 首先我…

kudu可视化工具:kudu-plus

目录 kudu kudu-plus是什么 kudu基础 分支说明 kudu-plus版本功能实现 kudu Kudu是为Apache Hadoop平台开发的列式数据库。Kudu拥有Hadoop生态系统应用程序的常见技术属性&#xff1a;它可以商用硬件上运行&#xff0c;可横向扩展&#xff0c;并支持高可用性操作。 kudu-p…

并发编程之循环屏障CyclicBarrier

文章目录 前言什么是CyclicBarrierCyclicBarrier原理CyclicBarrier VS CountDownLatchCountDownLatch图示&#xff1a;CyclicBarrier图示&#xff1a;两者的异同&#xff1a; CyclicBarrier核心源码实战演示1、创建测试demo2、创建测试用例3、查看测试结果 写在最后 前言 前面…

Ubuntu 20.04安装mysql8并配置远程访问

文章目录 一、使用apt-get安装mysql服务二、初始化mysql数据库管理员用户密码三、配置远程访问 一、使用apt-get安装mysql服务 # 更新软件源 apt-get install update# 安装mysql服务 apt-get install mysql-server# 使用mysqladmin工具查看mysql版本 mysqladmin --version# 启…

powershell定义文本,用户交互,正则表达式

定义文本 PS C:\Users\Administrator> $site"yuan" PS C:\Users\Administrator> $text"$site $(get-date) $env:windir" PS C:\Users\Administrator> $text yuan 09/16/2022 14:12:26 C:\Windows#使用单引号闭合字符串输出双引号 The site of my…

【Jeston Orin】Orin nano 8G模块使用官方系统包生成标准烧写系统测试

大家好&#xff0c;我是虎哥&#xff0c;GTC 2023上&#xff0c;NVIDIA正式推出了面向边缘AI的新一代入门款开发套件&#xff0c;Jetson Orin Nano Developer Kit。虽说只是入门套件&#xff0c;但据说相比上一代Jetson Nano有最高达80倍的性能提升&#xff01;于是我在收到包裹…

苹果ipad触控笔哪个好?平价电容笔排行榜

因为ipad本身的性能足够强大&#xff0c;所以现在已经有不少人开始使用它了。大屏幕上的教学效果很好&#xff0c;但如果只是为了用来看电视剧&#xff0c;那就没什么用了。如果你不想买一支价格昂贵的苹果电容笔&#xff0c;或只想用来做个学习笔记&#xff0c;这时&#xff0…

SpringBoot整合Nacos配置中心和注册中心

一、背景 公司项目中使用的Nacos作为服务的注册中心和配置中心&#xff0c;但是呢公司的这一套Nacos是经过封装了的&#xff0c;而且封装的不是很友好&#xff0c;想着自己搭建一套标注的Nacos配置中心和服务中心 二、Nacos配置中心和注册中心搭建 2.1 依赖引入 <!--注册…

端点中心配置

什么是桌面管理 桌面管理是管理组织内所有计算机系统的综合方法。尽管名称如此&#xff0c;桌面管理还包括监督组织内使用的笔记本电脑和其他计算设备。对于IT经理来说&#xff0c;使用户的计算机保持最新状态可能是一个挑战&#xff0c;特别是考虑到升级软件以防止安全漏洞的…

【Ubuntu18.04】Docker配置镜像源

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,YOLO领域博主爱笑的男孩。擅长深度学习,活动,YOLO,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个人简…

【二维矩阵如何存储在一维数组中(行优先和列优先)】

列优先和行优先的性能取决于具体的硬件架构和代码访问模式。在现代计算机中,内存访问的局部性(locality of reference)对性能至关重要。局部性分为两类:时间局部性(temporal locality)和空间局部性(spatial locality)。时间局部性表示最近访问过的数据项很可能在不久的…

加拿大留学思路自理

首先先看加拿大地图 留学加拿大的思路就应该是这样的&#xff1a; 1、清楚自己的需求 比如自己是移民向&#xff0c;所以首先就应该去加拿大官方网站Immigration and citizenship - Canada.ca 因为自己是理工科&#xff0c;之前在网络上看到别人总结的信息是说BC省理工类硕士…

【C++学习】类模板

类模板语法 #include<iostream> #include<string> using namespace std; //模板并不是万能的&#xff0c;有些特定数据类型&#xff0c;需要具体化方式做特殊实现 template<class NameType,class AgeType> class person { public:person(NameType name, Age…

k-means、决策树、svm算法总结

一、k-means算法 聚类算法&#xff1a; 一种典型的 无监督 学习算法&#xff0c;主要用于将相似的样本自动归到一个类别中。 在聚类算法中根据样本之间的相似性&#xff0c;将样本划分到不同的类别中&#xff0c;对于不同的相似度计算方法&#xff0c;会得到不同的聚类结果&…

【亲测有效】GnuTLS recv error (-110): The TLS connection was non-properly terminated.

【亲测有效】GnuTLS recv error [-110]: The TLS connection was non-properly terminated. 问题描述解决方法一&#xff1a;【取消代理】方法二【如果取消代理无用】方法三【这种方法对我有效】 问题描述 fatal: unable to access ‘https://github.com/openai/CLIP.git/’: …