算法:2-3平衡树与B树的详细探讨

2023-11-15

2-3树是最简单的B树,B+树是B树的升级

B树的来源

为什么要有树

  • 描述 1 - 多,N-M、层次等关系
  • 从最根本的原因来看,使用树结构是为了提升整体的效率:插入、删除、查找(索引),尤其是索引操作。因为相比于链表,一个平衡树的索引时间复杂度是 O ( l o g n ) O(log_n) O(logn), 而数组的索引时间复杂度是 O ( n ) O(n) O(n)
    在这里插入图片描述
  • 例子:数据库索引、文件索引等一般都是用树形结构存储的

第一种树:从bst树谈起

我们学的第一个树结果一般都是二叉查找树(BST)

特点:右子节点的数据要比根节点的大,左子节点的数据比根节点小,特殊情况下会变成一个链表。

二叉搜索树其期望高度(即为一棵平衡树时)为log2n,其各操作的时间复杂度(O(log2n))同时也由此而决定。但是,如果插入节点时,插入元素序列本身就是有序的,那么BST树就退化成一个线性表了,操作的时间复杂度为O(n), 之所以会变成O(n),是因为树的高度变大了,BST的比较次数最大是等于树的高度的。因此,如果想要减少比较次数,就需要降低树的高度。
在这里插入图片描述

为了解决上面的问题,我们引入了二叉搜索树

引入第二种树:avl树

构建二叉查找树时,当插入或者删除数据的时候,可能造成树的不平衡, 这个时候,我们可以通过旋转节点来调整树的高度,使得每个节点的左右两个子树的高度差的决定之不超过1(为什么要让高度差不超过1?这样才能保证整棵树的深度最小),这样的树叫做平衡二叉查找树(Self-balancing binary search tree)

平衡二叉搜索树又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

在平衡二叉搜索树中,我们可以看到,其高度一般都良好地维持在O(log(n)),大大降低了操作的时间复杂度。

在这里插入图片描述

  • 由于每次插入或删除节点后,都可能会破坏AVL的平衡,而要动态保证AVL的平衡需要很多操作,这些操作会影响整个数据结构的性能,除非是在树的结构变化特别少的情形下,否则AVL树平衡带来的搜索性能提升有可能还不足为了平衡树所带来的性能损耗。

为了解决 上面的问题,我们引入了红黑树

红黑树

--------------------------

像是红黑树、avl树等都是二叉树, 在二叉树的查找节点少的情况下,二叉树的操作效率较高。但是如果 二叉 树的节点很多( 海量数据存在数据库或文件中 ) , 又会出现新的问题:

  • 节点海量,会造成二叉树的高度很大,从而降低操作速度
  • 二叉树需要加载到内存的, 在构建二叉树时,需要多次进行 i/o 操作 (不同存储器间的数据读取称为I/O
  • 一般来说,我们操作大的数据都是存储在内存中的,而内存空间是有限的, 如果操作数据量大,内存放不下的时候,我们必须把一部分数据存放在外存中。
  • 对于外存中的数据,常见如数据库,我们通常通过索引表进行数据查找和交互,一般来说,索引表本身也很大,因为数据库中的数据非常多,因此索引也不可能全部存储在内存中,Mysql的MyISAM引擎的索引文件和数据文件是分离的,一张数据库表就有它对应的索引表,索引表中一个索引对应一条数据库记录的磁盘地址,内存中发起请求通过指定索引的查找索引表即可定位唯一的一条数据。
  • 因为索引文件同样存储在磁盘上,这样的话,索引查找过程中每查找一次就要产生一次磁盘I/O消耗,相对于CPU存取,I/O存取的消耗要高几个数量级,访问磁盘的成本大概是访问内存的十万倍左右。
  • 实际上,考虑到磁盘IO是非常高昂的操作,计算机操作已经系统做了一些优化,当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。
  • 在磁盘中读写1B的时间几乎与1KB一样快。同样,批量式访问:以页或块为单位,使用缓冲区。在涉及频繁处理大数据量的算法时,我们要么一次性若干个KB,要么一个字节也不访问
  • 每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关,一般为4k或8k大小的连续磁盘块,也就是我们读取一页内的数据时候,实际上才发生了一次IO,这个理论对于索引的数据结构设计非常有帮助,通常,索引节点的大小被设计为一页的大小。
  • 对于一旦涉及到这样的外部存储设备(外存),关于时间复杂度的计算就会发生变化,访问某个表/集合元素的时间已经不仅仅是寻找该元素所需比较次数的函数,我们必须考虑对硬盘IO进行操作的时间。由于IO耗时远大于CPU耗时,所以此处评价一个数据结构作为索引的优劣最重要的指标就是要尽量减少查找过程中磁盘IO的存取次数
  • 二叉树一个节点可以有多个孩子,但是它自身只存储一个元素,在元素非常多的时候,就使得要么树的度非常大(节点拥有子树的个数的最大值),要么树的高度非常大,甚至两者都必须足够大才行,这就使得IO次数非常多,这显然成了时间效率上的瓶颈,并且由于一次IO读取一个节点的数据,普通二叉树并不能容纳更多的数据,这样又造成了磁盘块空间的浪费。

为了解决上面的问题(主要是减少IO),我们必须将廋高的树变得“矮胖”,一个基本的想法就是:

  • 每个节点存储多个元素
  • 每个节点有更多的孩子

这就是多叉树。

多叉树之B树

在二叉树中,一个节点只能存储一个数据项,最多有两个子节点。在大数据量的情况下,树肯定会很高,此时查个数据对磁盘读个几千上万次那肯定是不行的。所以我们可以通过在一个节点中存放更多的数据项和引用更多的子节点(这样的树叫做N叉树):

  • 这样,树不用很高就可以标识很大的数据量了,检索次数就大大减少了
  • 用这种数据结构去磁盘中存取数据,磁盘IO次数的次数也会很少。

    多叉树矮胖, 二叉树廋高,使得多叉树非常适合存储在磁盘上。它充分利用了磁盘块的预读机制(局部性访问原理:当一个数据被用到时,其附近的数据也通常会马上被使用),通过缓存的方式进一步提升性能,磁盘在读取某一个文件指针的时候,通常会把紧挨着的数据,也全部读到缓存,因为实践证明,当一个文件数据被访问的时候,它周边的数据很快也会被访问。

B树是最常见的N叉树之一,常用于文件系统和数据库索引。

磁盘块和页的大小一般情况下为4KB,所以在B树中一个节点的最大存储数据个数的总大小一般不能超过4KB

  • 扇区:磁盘的最小存储单位;
  • 磁盘块:文件系统读写数据的最小单位;
  • 页:内存的最小存储单位;

【面试被怼】什么是B树?为啥文件/数据库索引要用B树而不用二叉查找树?

B树

B树又叫做平衡多路查找树(查找路径不只两个)

  • 平衡的意思是:
    • 左边和右边分布均匀
    • 从根节点,到每一个最底部的自己点,链路长度一致
  • 多路的意思是相对于二叉树而言的,二叉树就是二路查找树,查找时只有两条路,而B-tree有多条路,即父节点有多个子节点。

在这里插入图片描述
PS:

  • B树多结点多元素的特点是为了能存更多数据,减少io次数。而平衡二叉树才是解决二叉树出现的极端情况。
  • B树是对二叉查找树的改进, B树的设计思想是: 将相关数据尽量集中在一起,以便一次读取多个数据,减少硬盘操作次数。 B树为系统最优化大块数据的读和写操作。B树算法减少定位记录时所经历的中间构成,从而加快读取速度,普遍运用在数据库和文件系统。
  • 和平衡二叉树一样,B树也能以O(logn)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。不同的是,平衡二叉树是一般是用于优化内存中的数据的查找速度的数据结构,B树一般用于优化外存中数据的查找数据的数据结构,普遍运用在数据库索引结构和文件系统。
  • B树和平衡二叉树都是动态平衡的(也就是说失衡的时候会自动恢复平衡),但是恢复平衡的方法是不同的, AVL树是通过旋转来恢复平衡的,而B树是通过节点分裂来维持的

当我们描述一个B树时需要指定它的阶数, 阶数表示了一个节点最多有多少个孩子节点,一般用字母m表示阶数。

m阶B树特征:

  • 对于根节点: 根节点至少要有两个子节点, 其元素个数范围1<= k <= m-1

    • 当元素个数为0时:
      • 当前结构可以看成是空树、链表、结构体…
    • 当元素个数为1时:
      • 如果没有孩子,就是一个普通的节点,不是树
      • 如果有1个孩子,可以把结构看成是一个链表或者不平衡的树
      • 因为B树是平衡二叉搜索树,如果要达到平衡,那么它至少要有两个孩子
    • 推论:B是至少有3个节点:根节点和它的两个孩子
    • 因为当前树是m阶级B树, 对于这种结构的节点,每个节点最多只能有m-1个元素(包括根节点), 有m-1个元素的节点必须有m个子孩子[这样树才能平衡],当前孩子树是这棵树拥有的最大子节点树,这里的m就是当前树的阶,当前树就叫做m阶B树。
      在这里插入图片描述
  • 对于非根非叶节点(中间节点):每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m

    m阶B树的非根非叶结点至少要ceil(m/2)个孩子原因

  • 每个节点都存有索引和数据,也就是对应的key和value。

  • 每个节点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。

  • 树高平衡,也就是所有的叶节点都在同一层,或者说根节点到每个叶子节点的长度都相同。

  • B树把值接近的相关记录放在同一个磁盘页中,从而利用了访问的局部性原理。

比如,5阶的B树,那么根节点数量范围可能时:1 <= k <= 4, 非根节点数量范围:2 <= k <= 4。

ps :

  • 度数:在树中,每个节点的子节点(子树)的个数就称为该节点的度(degree)。

  • 阶数:(Order)阶定义为一个节点的子节点数目的最大值。(自带最大值属性)

B树的相关操作

B树插入

插入的时候,记住一个原则: 判断当前节点key的个数是否小于等于m-1,如果满足,直接插入即可,如果不满足,用节点的中间的key将这个节点分为两部分,

例子:在5阶B树中,结点最多有4个key,最少有2个key(注意:下面的节点统一用一个节点表示key和value)

  • 插入18,70,50,40
    在这里插入图片描述
  • 插入22
    在这里插入图片描述

插入22时,发现这个节点的关键字已经大于4了,所以需要进行分裂,分裂之后,如下
在这里插入图片描述

  • 接着插入23,25,39
    在这里插入图片描述
    分裂,得到下面的
    在这里插入图片描述
    --

B树删除

  • 初始B树(可以看出下面是一个4阶B树, 非叶子节点必须key个数[4/2, 4-1] --> [2, 3])
    在这里插入图片描述
  • 删除15,这种情况是删除叶子节点的元素,如果删除之后,节点数2 还是还在范围内[M/2, M-1],这种情况只要直接删除即可
    在这里插入图片描述
    在这里插入图片描述
  • 接着,我们把22删除,这种情况的规则:22是非叶子节点,对于非叶子节点的删除,我们需要用后继key(元素)覆盖要删除的key,然后在后继key所在的子支中删除该后继key。对于删除22,需要将后继元素24移到被删除的22所在的节点。
    在这里插入图片描述
    在这里插入图片描述
    此时发现26所在的节点只有一个元素,小于2个(m/2),这个节点不符合要求,这时候的规则(向兄弟节点借元素):如果删除叶子节点,如果删除元素后元素个数少于(m/2),并且它的兄弟节点的元素大于(m/2),也就是说兄弟节点的元素比最少值m/2还多,将先将父节点的元素移到该节点,然后将兄弟节点的元素再移动到父节点。这样就满足要求了。

我们看看操作过程就更加明白了。
在这里插入图片描述

  • 接着删除28,删除叶子节点,删除后不满足要求,所以,我们需要考虑向兄弟节点借元素,但是,兄弟节点也没有多的节点(2个),借不了,怎么办呢?如果遇到这种情况,首先,还是将先将父节点的元素移到该节点,然后,将当前节点及它的兄弟节点中的key合并,形成一个新的节点。
    在这里插入图片描述
    移动之后,跟兄弟节点合并。

在这里插入图片描述

最简单的B树:2-3树

2-3树是最简单的B树结构。所谓2-3树,即满足二叉搜索树的性质,且节点可以存放一个元素或者两个元素,每个非叶子节点有两个或三个孩子的树(意思是查找路径可能有2个,可能有3个),而且所有叶都在统一层上。

  • 性质1:满足二叉搜索树的性质。
  • 性质2:节点可以存放一个或两个元素
  • 性质3:每个节点有两个或三个子节点
  • 性质4:因为2-3树是一个B树,B树又叫做平衡二叉查找树, 所以2-3树是一颗绝对平衡的树: 从根节点到任意叶子节点所经过的节点相同, 即2-3 树的所有叶子节点都在同一层, 是 B 树都满足这个条件 )

在这里插入图片描述

2-3树存在以下两种节点:2-节点(存在两个子节点)和3-节点(存在3个子节点)

  • 每个节点的key从左到右保持了从小到大的顺序,两个key之间的子树中所有的key一定大于它的父节点的左key,小于父节点的右key
    在这里插入图片描述

2-3树的创建

两条规则:

  • 规则1: 不能往空的子树上新增元素
  • 规则2: 四节点可以被分解三个2-节点组成的树,并且分解后新树的根节点需要向上和父节点融合
    • 2-3可以看成是一个3阶的B树, 也就是说
      • 每个节点最多可以有2个数据,当插入数据之后,如果发现节点的树等于3的时候,就要开始分裂当前节点数了
      • 对于非叶子节点,每个节点至少要有3/2=1个数据。
示例1

在这里插入图片描述

  • α,向节点1插入数据2,此时为了保持平衡,不会新产生分支,只会在一个节点中存放两个节点。
  • β,继续插入数据3,此时这个节点有三数据,1、2、3,是一个临时区域。
  • γ,把三个数据的节点,中间节点拉起来,调整成树形结构。
  • δ,继续插入数据4,为了保持树平衡,会插在节点3的右侧。
  • ε,继续插入数据5,插入后3、4、5共用1个节点,当一个节点上有三个数据时候,则需要进行调整。
  • ζ,中间节点4向上⏫调整,调整后,1节点在左、3节点在中间、5节点在右。
  • η ,继续插入数据6,在保持树平衡的情况下,与节点5公用。
  • θ ,继续插入数据7,插入后,节点7会与当前的节点 5 6 共用。此时是一个临时存放,需要调整。初步调整后,抽出6节点,向上存放,变为2 4 6共用一个节点,这是一个临时状态,还需要继续调整。
  • ι,因为根节点有三个数据2、4、6,则继续需要把中间节点上移,1、3和5、7 则分别成二叉落到节点2、节点6上。
示例2

数据:[42,37,18,12,11,6,5]

1、使用42初始化根节点
在这里插入图片描述

2、加入节点37: 如果按照一般的二叉搜索树的规则,37应该添加到42的左子树上,但是创建2-3树的时候,规定了不能往空的子树上新增元素, 因此我们需要把37和42继续融合,使之成为一个3节点

在这里插入图片描述

3、加入节点18: 同样,18与[37, 42]进行融合,使之成为一个4节点

在这里插入图片描述
4、添加18之后,出现了4节点,这个时候我们要将4节点拆分成为一颗新的树
在这里插入图片描述
5、插入12: 同样,节点12需要和18节点融合
在这里插入图片描述
6、插入11:
在这里插入图片描述
此时当前节点key数达到了3,需要拆分当前节点
在这里插入图片描述
拆分节点之后,树失去了平衡,我们需要将拆分后的子树的根节点向上融合
在这里插入图片描述
7、插入节点6
在这里插入图片描述

8、插入节点5
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

删除数据

有了上面数据插入的学习,在看数据删除其实就是一个逆向的过程,在删除的主要包括这样两种情况;

  • 删除了3-节点,也就是包含两个数据元素的节点,直接删除即可,不会破坏树平衡。
  • 删除了2-节点,此时会破坏树平衡,需要将树高缩短或者元素合并,恢复树平衡。
示例1

把数据再从7、6、5、4、3、2、1顺序删除,观察2-3树的结构变化,如下
在这里插入图片描述

  • α,删除节点7,因为节点7只有一个数据元素,删除节点5、6合并,但此时破坏了2-3树的平衡性,需要缩短树高进行调整。
  • β,因为删除节点后,整个树结构不平衡,所以需要缩短树高,调整元素。节点2、4合并,节点1、3分别插入左侧和中间。
  • γ,删除节点6,这个节点是3-节点(可以分出3个叉的意思),删除后不会破坏树平衡,保持不变。
  • δ,删除节点5,此时会破坏树平衡,需要把跟节点4下放,与3合并。
  • ε,删除节点4,这个节点依旧是3-节点,所以不需要改变树结构。
  • ζ,删除节点3,此时只有1、2节点,需要合并。
  • η ,删除节点2,此时节点依旧是3-节点,所以不需要改变树结构。
示例2

在这里插入图片描述

  • 删除4,其实需要将节点3、5合并,指向节点2,保持树平衡。
  • 删除7,节点8、9合并。
  • 删除14,节点15上移,恢复成3-叉树。
总结
  • 删除的是非叶子节点:使用中序遍历下的直接后继节点key来覆盖当前节点key,再删除用来覆盖的后继节点key
    在这里插入图片描述

  • 删除叶子节点

    • 当前节点是3节点(有2个key):直接删除key
      在这里插入图片描述

    • 当前节点是2节点(有1个key):删除节点,然后判断

      • 当前节点的双亲节点是2节点(有1个key),兄弟是3节点(2个key): 将双亲节点移动到当前位置,再将兄弟节点中最接近当前位置的key移动到双亲节点中
        在这里插入图片描述

      • 当前节点的双亲节点是2节点(有1个key),兄弟是2节点(1个key):先通过移动兄弟节点的中序遍历直接后驱到兄弟节点,以使兄弟节点变为3-节点;再进行上面的操作
        在这里插入图片描述

      • 当前节点的双亲节点是3-节点(2个key):拆分双亲节点使其成为2-节点(1个key),再将再将双亲节点中最接近的一个拆分key与中孩子合并,将合并后的节点作为当前节点
        在这里插入图片描述

      • 2-3树是一颗满二叉树,将2-3树层树减少,并将兄弟节点合并到双亲节点中,同时将双亲节点的所有兄弟节点合并到双亲节点的双亲节点中,如果生成了-4节点,再分解4-节点即可
        在这里插入图片描述

查找数据

基本原则:

  • 小于当前节点值,左侧寻找
  • 大于当前节点值,右侧寻找
  • 一直到找到索引值,停止
    在这里插入图片描述


一个节点中有几个孩子就有几条搜索路径

面试官问你B树和B+树,就把这篇文章丢给他
面经手册 · 第5篇《看图说话,讲解2-3平衡树「红黑树的前身」》–看完了
浅析——B树,B+树,B*树以及分析MySQL的两种引擎
2-3树与2-3-4树
数据结构树,为什么是B+树
一步步分析为什么B+树适合作为索引的结构
https://blog.csdn.net/u010916338/article/details/86134334
B树的查找、插入、删除
二叉查找树、平衡二叉树、红黑树、B-/B+树性能对比
https://blog.csdn.net/m0_38075425/article/details/81777364
https://blog.csdn.net/m0_38075425/article/details/81777364
https://blog.csdn.net/weixin_43767015/article/details/105880671?utm_medium=distribute.pc_relevant.none-task-blog-title-4&spm=1001.2101.3001.4242

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

算法:2-3平衡树与B树的详细探讨 的相关文章

随机推荐

  • 【扩展KMP】POJ_3450| HDU_2328 Corporate Identity

    原题直通车 POJ 3450 Corporate Identity HDU 2328 Corporate Identity 题意概述 找出N个串中最长公共子串 分析 一 可以直接枚举其中一个串的所有字串 跟所有串进行匹配找到结果 二 用其中
  • IDEA(Ultimate版本)安装全程照着箭头指示

    只需动手跟着箭头指示安装即可 安装包的链接 https pan baidu com s 12hSGc7PDpbcaV UxCL5NSQ 提取码 zx1x 下载后解压自己想要的位置 安装完后可删除 以上就是安装全过程 如有问题可在评论区留言
  • 2023-05-19 题目

    1 java的三大特性 亦或者四大特性 继承 继承是从已有类得到继承信息创建新类的过程 提供继承信息的类被称为父类 超类 基类 得到继 承信息的类被称为子类 派生类 继承让变化中的软件系统有了一定的延续性 同时继承也是封装程序中可变因素的
  • <<计算机视觉CVPR>>2022:Grounded Language-Image Pre-training

    收录情况 CVPR 2022 论文链接 https arxiv org abs 2112 03857 代码链接 https github com microsoft GLIP 文章目录 简介 问题 方案 主要贡献 相关工作 方法 Groun
  • 12款开源或免费的3D建模软件

    1 Blender Blende是一款系统全面的3D建模套件 它提供了大量专业级功能和模块 跨平台支持所有的主要操作系统 目前并已成为免费3D软件的代名词 Blender通常被称为TheBlenderProject 因为它不仅仅是一个软件
  • Python 基础合集13:错误的调试和处理

    一 前言 本小节介绍了错误的调试和处理 包含了寻找出现bug的代码的方法 以及处理bug的方法 另外还附加了一些错误类型 环境说明 Python 3 6 windows11 64位 二 调试 找出错误 之前看到一句话 很在理 出错并不可怕
  • 汇编, 立即数, 有符号与无符号数

    汇编 立即数 有符号与无符号数 386 model flat stdcall option casemap none includelib msvcrt lib printf proto c ptr sbyte vararg data sz
  • C++语法总结

    1 const 与volatile 的用法 1 const include
  • 传统直线检测算法与基于深度学习的直线检测算法

    传统直线检测算法与基于深度学习的直线检测算法 提示 科大讯飞算法面试题 加入一个图像有一条很明显的直线划痕 怎么用传统图像处理去掉划痕 就是直线检测 文章目录 传统直线检测算法与基于深度学习的直线检测算法 TOC 文章目录 啥是直线检测 传
  • 【Python蓝桥杯】01字串 对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能。它们的前几个是: 00000 00001 00010 00011 00100 请按从小到大的顺序输出

    最近在刷蓝桥杯题目 按题目做一下笔记整理 顺便分享交流一下 有更好的解决方案欢迎大家共同提出探讨 以下源代码为系统提交满分答案 01字串 问题描述 资源限制 Python时间限制 5 0s 问题描述 对于长度为5位的一个01串 每一位都可能
  • JS数据结构与算法知识点--->字典

    此数据结构算法知识点系列笔记均是看coderwhy老师视频整理得出 字典一般是基于哈希表 后续学习 实现 数组 字典 集合 是几乎编程语言都会默认提供的数据类型 特点 一 一对应的关系 使用字典的方式 可以通过key取出value 键值对
  • SolidWorks装配体中子装配体无法移动的问题

    SolidWorks装配体中子装配体无法移动的问题 问题描述 问题解决 问题描述 有时候在一个装配体中有一个子装配体 这个子装配体没有被完全定义 子装配体之间的零件是可以相互移动的 但是在装配体中子装配体中的零件不可以相互移动 如下图 问题
  • CAN总线的报文分析(三)

    系列文章目录 文章目录 系列文章目录 前言 一 数据帧 最常用 1 帧起始 2 仲裁段 3 控制段 4 数据段 5 CRC段 6 ACK段 7 帧结束 二 远程帧 三 错误帧 四 过载帧 五 帧间隔 总结 前言 CAN总线上的节点发送数据都
  • Python for 3dMax加载图像文件并读取像素值

    使用Python for 3dMax加载和显示图像文件的示例 在这种情况下 EXR图像文件与3dMax文件位于同一目录中 from MaxPlus import BitmapManager image file path r BG park
  • 【编程笔试】美团2021校招笔试-通用编程题第5场(附思路及C++代码)

    导览 练习地址 修改大小写 式子求值 争夺地盘 公司管理 总结 练习地址 点此前往练习 修改大小写 在小美的国家 任何一篇由英文字母组成的文章中 如果大小写字母的数量不相同会被认为文章不优雅 现在 小美写了一篇文章 并且交给小团来修改 小美
  • 爬虫小项目

    爬取同花顺官网中的数据 共四页 项目适合练手 最终保存在csv文件中 尚有缺点 先发出来 一起探讨 qq 2385455226 欢迎来访 import requests from lxml import html headers Accep
  • 光线追踪渲染实战(五):低差异序列与重要性采样,加速收敛!

    项目代码仓库 GitHub https github com AKGWSB EzRT gitee https gitee com AKGWSB EzRT 目录 前言 1 低差异序列介绍 2 sobol 序列及其实现 2 1 生成矩阵与递推式
  • 面试官:线程崩了,为什么不会导致 JVM 崩溃呢?如果是主线程呢?

    网上看到一个很有意思的美团面试题 为什么线程崩溃崩溃不会导致 JVM 崩溃 这个问题我看了不少回答 但发现都没答到根上 所以决定答一答 相信大家看完肯定会有收获 本文分以下几节来探讨 线程崩溃 进程一定会崩溃吗 进程是如何崩溃的 信号机制简
  • Python中装饰器超详细讲解,看不懂尽管来砍我!

    Python中装饰器的那些事儿 说到装饰器 我们需要首先理解下闭包的概念 走起 定义 具有执行环境的函数 满足三个条件 1 外部函数中定义一个内部函数 2 内部函数中使用外部函数的局部变量 3 外部函数将内部函数作为返回值返回 此时的内部函
  • 算法:2-3平衡树与B树的详细探讨

    2 3树是最简单的B树 B 树是B树的升级 B树的来源 为什么要有树 描述 1 多 N M 层次等关系 从最根本的原因来看 使用树结构是为了提升整体的效率 插入 删除 查找 索引 尤其是索引操作 因为相比于链表 一个平衡树的索引时间复杂度是