BST树,AVL树, B树, B-树, B+树, B*树,红黑树RBT, 堆积树(堆), 字典树Trie,跳表

本文深入探讨了多种树型数据结构,包括二叉查找树、平衡二叉树、B树、B+树、B*树、红黑树、堆积树、Trie树和跳表。分析了每种树的特点、操作代价、效率总结及其适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://blog.youkuaiyun.com/Beyond_2016/article/details/81202511
https://www.cnblogs.com/leng2052/p/5323954.html
https://www.cnblogs.com/lca1826/p/6484469.html

1. 二叉查找树 (Binary Search Tree)

很显然,二叉查找树的发现完全是因为静态查找结构在动态插入,删除结点所表现出来的无能为力(需要付出极大的代价)。
在这里插入图片描述在这里插入图片描述
BST 的操作代价分析:

(1) 查找代价: 任何一个数据的查找过程都需要从根结点出发,沿某一个路径朝叶子结点前进。因此查找中数据比较次数与树的形态密切相关。

     当树中每个结点左右子树高度大致相同时,树高为logN。则平均查找长度与logN成正比,查找的平均时间复杂度在O(logN)数量级上。

     当先后插入的关键字有序时,BST退化成单支树结构。此时树高n。平均查找长度为(n+1)/2,查找的平均时间复杂度在O(N)数量级上。

(2) 插入代价: 新结点插入到树的叶子上,完全不需要改变树中原有结点的组织结构。插入一个结点的代价与查找一个不存在的数据的代价完全相同。

(3) 删除代价: 当删除一个结点P,首先需要定位到这个结点P,这个过程需要一个查找的代价。然后稍微改变一下树的形态。如果被删除结点的左、右子树只有一个存在,则改变形态的代价仅为O(1)。如果被删除结点的左、右子树均存在,只需要将当P的左孩子的右孩子的右孩子的...的右叶子结点与P互换,在改变一些左右子树即可。因此删除操作的时间复杂度最大不会超过O(logN)。

(4)二叉查找树比普通树查找更快,查找、插入、删除的时间复杂度为O(logN)。但是二叉查找树有一种极端的情况,就是会变成一种线性链表似的结构。此时时间复杂度就变味了O(N),为了解决这种情况,出现了二叉平衡树。

BST效率总结 :  查找最好时间复杂度O(logN),最坏时间复杂度O(N)。
                        插入删除操作算法简单,时间复杂度与查找差不多

2. 平衡二叉查找树 ( Balanced Binary Search Tree )

二叉查找树在最差情况下竟然和顺序查找效率相当,这是无法仍受的。事实也证明,当存储数据足够大的时候,树的结构对某些关键字的查找效率影响很大。当然,造成这种情况的主要原因就是BST不够平衡(左右子树高度差太大)。

既然如此,那么我们就需要通过一定的算法,将不平衡树改变成平衡树。因此,AVL树就诞生了。

AVL 的操作代价分析:

(1) 查找代价: AVL是严格平衡的BST(平衡因子不超过1)。那么查找过程与BST一样,只是AVL不会出现最差情况的BST(单支树)。因此查找效率最好,最坏情况都是O(logN)数量级的。

(2) 插入代价: AVL必须要保证严格平衡(|bf|<=1),那么每一次插入数据使得AVL中某些结点的平衡因子超过1就必须进行旋转操作。事实上,AVL的每一次插入结点操作最多只需要旋转1次(单旋转或双旋转)。因此,总体上插入操作的代价仍然在O(logN)级别上(插入结点需要首先查找插入的位置)。

(3) 删除代价:AVL删除结点的算法可以参见BST的删除结点,但是删除之后必须检查从删除结点开始到根结点路径上的所有结点的平衡因子。因此删除的代价稍微要大一些。每一次删除操作最多需要O(logN)次旋转。因此,删除操作的时间复杂度为O(logN)+O(logN)=O(2logN)

AVL 效率总结 :  查找的时间复杂度维持在O(logN),不会出现最差情况

                        AVL树在执行每个插入操作时最多需要1次旋转,其时间复杂度在O(logN)左右。

                        AVL树在执行删除时代价稍大,执行每个删除操作的时间复杂度需要O(2logN)。

平衡二叉树是一种自平衡的树。

AVL树也规定了左结点小于根节点,右结点大于根节点。并且还规定了左子树和右子树的高度差不得超过1。这样保证了它不会成为线性的链表。AVL树的查找稳定,查找、插入、删除的时间复杂度都为O(logN),但是由于要维持自身的平衡,所以进行插入和删除结点操作的时候,需要对结点进行频繁的旋转。

AVL树每一个节点只能存放一个元素,并且每个节点只有两个子节点。当进行查找时,就需要多次磁盘IO,(数据是存放在磁盘中的,每次查询是将磁盘中的一页数据加入内存,树的每一层节点存放在一页中,不同层数据存放在不同页。)这样如果需要多层查询就需要多次磁盘IO。为了解决AVL树的这个问题,就出现了B树

3. B树:

B树也叫平衡树,也叫作B-树,英文为Blance-Tree。是一种多路平衡树。
在这里插入图片描述
一个m阶的B树规定了:

1.根结点至少有两个子女。

2.每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m 。

3.每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m。

4.所有的叶子结点都位于同一层。

5.每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划

B树每一层存放了更多的节点,由AVL树的“瘦高”变成了“矮胖”。可以相对减少磁盘IO的次数。MongoDB的索引就是用B树实现的。

B树也是一种自平衡的树,在进行插入和删除操作时也需要对结点进行旋转等操作。

B-树的搜索,从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则结束,否则进入查询关键字所属范围的儿子结点;重复,直到所对应的儿子指针为空,或已经是叶子结点;

B-树的特性:

   1.关键字集合分布在整颗树中;

   2.任何一个关键字出现且只出现在一个结点中;

   3.搜索有可能在非叶子结点结束;

   4.其搜索性能等价于在关键字全集内做一次二分查找;

   5.自动层次控制;

不过,B树的查找不稳定,最好的情况就是在根节点查到了,最坏的情况就是在叶子结点查到。另外,B树在遍历方面比较麻烦,由于需要进行中序遍历,所以也会进行一定数量的磁盘IO。为了解决这些问题,出现了B+树。

4. B+树:

B+树每个非叶子结点存放的元素只用于索引作用,所有数据保存在叶子结点。
在这里插入图片描述
一个m阶的B+树规定了:

1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。

2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。

3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素
链接!

B+树是B-树的变体,也是一种多路搜索树:

   1.其定义基本与B-树同,除了:

   2.非叶子结点的子树指针与关键字个数相同;

   3.非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树

(B-树是开区间);

   5.为所有叶子结点增加一个链指针;

   6.所有关键字都在叶子结点出现;

B+的搜索与B-树也基本相同,区别是B+树只有达到叶子结点才命中(B-树可以在

非叶子结点命中),其性能也等价于在关键字全集做一次二分查找;

   B+的特性:

   1.所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;

   2.不可能在非叶子结点命中;

   3.非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存(关键字)数据的数据层;

   4.更适合文件索引系统
   因为非叶子结点中存放的元素不存放数据,所以每一层可以容纳更多元素,也就是磁盘中的每一页可以存放更多元素。这样在查找时,磁盘IO的次数也会减少。

另外,B+树的查找稳定,因为所有的数据都在叶子结点。每个叶子结点也通过指针指向构成了一种链表结构,所以遍历数据也会简单很多。

B和B+树主要用在文件系统以及数据库做索引.比如Mysql
B+树的插入和删除和B树类似。

问题:B/B+树性能分析 
n个节点的平衡二叉树的高度为H(即logn),而n个节点的B/B+树的高度为logt((n+1)/2)+1;

若要作为内存中的查找表,B树却不一定比平衡二叉树好,尤其当m较大时更是如此.因为查找操作CPU的时间在B-树上是O(mlogtn)=O(lgn(m/lgt)),而m/lgt>1;所以m较大时O(mlogtn)比平衡二叉树的操作时间大得多. 因此在内存中使用B树必须取较小的m.(通常取最小值m=3,此时B-树中每个内部结点可以有2或3个孩子,这种3阶的B-树称为2-3树)。

6、为什么说B+tree比B树更适合实际应用中操作系统的文件索引和数据索引.

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

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

ps:我在知乎上看到有人是这样说的,我感觉说的也挺有道理的:
他们认为数据库索引采用B+树的主要原因是:B树在提高了IO性能的同时并没有解决元素遍历的我效率低下的问题,正是为了解决这个问题,B+树应用而生.B+树只需要去遍历叶子节点就可以实现整棵树的遍历.而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作(或者说效率太低).

5. B*树

是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;
在这里插入图片描述
B*树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3

(代替B+树的1/2);

   B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据

复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父

结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针;

   B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分

数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字

(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之

间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针;

所以,B*树分配新结点的概率比B+树要低,空间使用率更高;

B树总结:

在磁盘中组织查找结构,从任何一个结点指向其他结点都有可能读取一次磁盘数据,再将数据写入内存进行比较。大家都知道,频繁的磁盘IO操作,效率是很低下的(机械运动比电子运动要慢不知道多少)。显而易见,所有的二叉树的查找结构在磁盘中都是低效的。因此,B树很好的解决了这一个问题。

B-Tree的操作代价分析:

(1) 查找代价: B-Tree作为一个平衡多路查找树(m-叉)。B树的查找分成两种:一种是从一个结点查找另一结点的地址的时候,需要定位磁盘地址(查找地址),查找代价极高。另一种是将结点中的有序关键字序列放入内存,进行优化查找(可以用折半),相比查找代价极低。而B树的高度很小,因此在这一背景下,B树比任何二叉结构查找树的效率都要高很多。而且B+树作为B树的变种,其查找效率更高。

(2)插入代价: B-Tree的插入会发生结点的分裂操作。当插入操作引起了s个节点的分裂时,磁盘访问的次数为h(读取搜索路径上的节点)+2s(回写两个分裂出的新节点)+1(回写新的根节点或插入后没有导致分裂的节点)。因此,所需要的磁盘访问次数是h+2s+1,最多可达到3h+1。因此插入的代价是很大的。

(3)删除代价:B-Tree的删除会发生结点合并操作。最坏情况下磁盘访问次数是3h=(找到包含被删除元素需要h次

读访问)+(获取第2至h层的最相邻兄弟需要h-1次读访问)+(在第3至h层的合并需要h-2次写
访问)+(对修改过的根节点和第2层的两个节点进行3次写访问)

B-Tree效率总结: 由于考虑磁盘储存结构,B树的查找、删除、插入的代价都远远要小于任何二叉结构树(读写磁盘次数的降低)。

动态查找树结构的对比:

(1) 平衡二叉树和红黑树 [AVL PK RBT]

  AVL 和RBT 都是二叉查找树的优化。其性能要远远好于二叉查找树。他们之间都有自己的优势,其应用上也有不同。

  结构对比: AVL的结构高度平衡,RBT的结构基本平衡。平衡度AVL > RBT.

  查找对比: AVL 查找时间复杂度最好,最坏情况都是O(logN)。

                  RBT 查找时间复杂度最好为O(logN),最坏情况下比AVL略差。

  插入删除对比:  1. AVL的插入和删除结点很容易造成树结构的不平衡,而RBT的平衡度要求较低。因此在大量数据插入的情况下,RBT需要通过旋转变色操作来重新达到平衡的频度要小于AVL。

                         2. 如果需要平衡处理时,RBT比AVL多一种变色操作,而且变色的时间复杂度在O(logN)数量级上。但是由于操作简单,所以在实践中这种变色仍然是非常快速的。

                         3. 当插入一个结点都引起了树的不平衡,AVL和RBT都最多需要2次旋转操作。但删除一个结点引起不平衡后,AVL最多需要logN 次旋转操作,而RBT最多只需要3次。因此两者插入一个结点的代价差不多,但删除一个结点的代价RBT要低一些。

                         4. AVL和RBT的插入删除代价主要还是消耗在查找待操作的结点上。因此时间复杂度基本上都是与O(logN) 成正比的。

    总体评价:大量数据实践证明,RBT的总体统计性能要好于平衡二叉树。

(2) B~树和B+树 [ B~Tree PK B+Tree]

  B+树是B~树的一种变体,在磁盘查找结构中,B+树更适合文件系统的磁盘存储结构。

  结构对比: B~树是平衡多路查找树,所有结点中都包含了待查关键字的有效信息(比如文件磁盘指针)。每个结点若有n个关键字,则有n+1个指向其他结点的指针。

                 B+树严格意义上说已经不是树,它的叶子结点之间也有指针链接。B+树的非终结点中并不含有关键字的信息,需要查找的关键字的全部信息都包含在叶子结点上。非终结点中只作为叶子结点关键字的索引而存在。

  查找对比:1. 在相同数量的待查数据下,B+树查找过程中需要调用的磁盘IO操作要少于普通B~树。由于B树所在的磁盘存储背景下,因此B+树的查找性能要好于B~树。

                 2. B+树的查找效率更加稳定,因为所有叶子结点都处于同一层中,而且查找所有关键字都必须走完从根结点到叶子结点的全部历程。因此同一颗B+树中,任何关键字的查找比较次数都是一样的。而B树就不一定了,可能查找到某一个非终结点就结束了。

  插入删除对比:  B+树与B~树在插入删除操作中的效率是差不多的。

总体评价:在应用背景下,特别是文件结构存储中。B+树的应用要更多,其效率也要比B-树好

6.红黑树

也叫RB树,RB-Tree。是一种自平衡的二叉查找树,它的节点的颜色为红色和黑色。它不严格控制左、右子树高度或节点数之差小于等于1。也是一种解决二叉查找树极端情况的数据结构。

一种二叉查找树,但在每个节点增加一个存储位表示节点的颜色,可以是red或black. 通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍.它是一种弱平衡二叉树(由于是若平衡,可以推出,相同的节点情况下,AVL树的高度低于红黑树),相对于要求严格的AVL树来说,它的旋转次数变少,所以对于搜索,插入,删除操作多的情况下,我们就用红黑树.
在这里插入图片描述
在这里插入图片描述
红黑树规定了:
红黑树的每个节点上的属性除了有一个key、3个指针:parent、lchild、rchild以外,还多了一个属性:color。它只能是两种颜色:红或黑。而红黑树除了具有二叉搜索树的所有性质之外,还具有以下4点性质:

  1. 根节点是黑色的。
  2. 空节点是黑色的(红黑树中,根节点的parent以及所有叶节点lchild、rchild都不指向NULL,而是指向一个定义好的空节点)。
  3. 红色节点的父、左子、右子节点都是黑色。
  4. 在任何一棵子树中,每一条从根节点向下走到空节点的路径上包含的黑色节点数量都相同
  5. 红黑树只追求近似平衡,所以在插入与删除节点时,翻转次数远远少于平衡树,因此在需要较多插入删除操作的场景中,使用红黑树更好。同样也因为近似平衡,所以在查询时,红黑树查询的深度可能会大于平衡二叉树,所以在需要较多查询的场景中,使用平衡二叉树更好。

红黑树近似平衡:深度最大的节点的深度<= 2 * 深度最小的节点的深度。

1.节点是红色或黑色。

2.根节点是黑色。

3.每个叶子节点都是黑色的空节点(NIL节点)。

4 每个红色节点的两个子节点都是黑色。也就是说从每个叶子到根的所有路径上不能有两个连续的红色节点)。

5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

(1)红黑树在查找方面和AVL树操作几乎相同。但是在插入和删除操作上,AVL树每次插入删除会进行大量的平衡度计算,红黑树是牺牲了严格的高度平衡的优越条件为代价,它只要求部分地达到平衡要求,结合变色,降低了对旋转的要求,从而提高了性能。红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。

(2)相比于BST,因为红黑树可以能确保树的最长路径不大于两倍的最短路径的长度,所以可以看出它的查找效果是有最低保证的。在最坏的情况下也可以保证O(logN)的,这是要好于二叉查找树的。因为二叉查找树最坏情况可以让查找达到O(N)。

(3)红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高,所以在插入和删除中所做的后期维护操作肯定会比红黑树要耗时好多,但是他们的查找效率都是O(logN),所以红黑树应用还是高于AVL树的. 实际上插入 AVL 树和红黑树的速度取决于你所插入的数据.如果你的数据分布较好,则比较宜于采用 AVL树(例如随机产生系列数),但是如果你想处理比较杂乱的情况,则红黑树是比较快的。

(4)红黑树广泛用于TreeMap、TreeSet,以及jdk1.8后的HashMap。

二叉平衡树的严格平衡策略以牺牲建立查找结构(插入,删除操作)的代价,换来了稳定的O(logN) 的查找时间复杂度。但是这样做是否值得呢?

能不能找一种折中策略,即不牺牲太大的建立查找结构的代价,也能保证稳定高效的查找效率呢? 答案就是:红黑树。

重要特点:

1. 每个红色结点的两个子节点必须是黑色的。换句话说:从每个叶子到根的所有路径上不能有两个连续的红色结点

2.从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点

所以, 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。

RBT 的操作代价分析:

(1) 查找代价:由于红黑树的性质(最长路径长度不超过最短路径长度的2倍),可以说明红黑树虽然不像AVL一样是严格平衡的,但平衡性能还是要比BST要好。其查找代价基本维持在O(logN)左右,但在最差情况下(最长路径是最短路径的2倍少1),比AVL要略逊色一点。

(2) 插入代价:RBT插入结点时,需要旋转操作和变色操作。但由于只需要保证RBT基本平衡就可以了。因此插入结点最多只需要2次旋转,这一点和AVL的插入操作一样。虽然变色操作需要O(logN),但是变色操作十分简单,代价很小。

(3) 删除代价:RBT的删除操作代价要比AVL要好的多,删除一个结点最多只需要3次旋转操作。

RBT 效率总结 : 查找 效率最好情况下时间复杂度为O(logN),但在最坏情况下比AVL要差一些,但也远远好于BST。

插入和删除操作改变树的平衡性的概率要远远小于AVL(RBT不是高度平衡的)。因此需要的旋转操作的可能性要小,而且一旦需要旋转,插入一个结点最多只需要旋转2次,删除最多只需要旋转3次(小于AVL的删除操作所需要的旋转次数)。虽然变色操作的时间复杂度在O(logN),但是实际上,这种操作由于简单所需要的代价很小。

B树:二叉树,每个结点只存储一个关键字,等于则命中,小于走左结点,大于走右结点;

   B-树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点;

   所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中;

   B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中;

   B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率

从1/2提高到2/3;

应用:
(1)广泛用于C++的STL中,map和set都是用红黑树实现的.
(2)@著名的linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块,进程的虚拟内存区域都存储在一颗红黑树上,每个虚拟地址区域都对应红黑树的一个节点,左指针指向相邻的地址虚拟存储区域,右指针指向相邻的高地址虚拟地址空间.
(3)IO多路复用epoll的实现采用红黑树组织管理sockfd,以支持快速的增删改查.
(4)ngnix中,用红黑树管理timer,因为红黑树是有序的,可以很快的得到距离当前最小的定时器.
(5)java中TreeMap的实现.

7. 堆积树(堆)

父节点的值大于(小于)两个子节点的值(分别称为大顶堆和小顶堆)。它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等
堆的基本操作

堆是一棵完全二叉树,高度为O(lg n),其基本操作至多与树的高度成正比。在介绍堆的基本操作之前,先介绍几个基本术语:

    A:用于表示堆的数组,下标从1开始,一直到n
    
    PARENT(t):节点t的父节点,即floor(t/2)
    
    RIGHT(t):节点t的左孩子节点,即:2*t

   LEFT(t):节点t的右孩子节点,即:2*t+1

   HEAP_SIZE(A):堆A当前的元素数目

8.Trie树

又名单词查找树,一种树形结构,常用来操作字符串。它是不同字符串的相同前缀只保存一份。相对直接保存字符串肯定是节省空间的,但是它保存大量字符串时会很耗费内存。

类似的有前缀树(prefix tree),后缀树(suffix tree),radix tree(patricia tree, compact prefix tree),crit-bit tree(解决耗费内存问题),以及前面说的double array trie。

使用场景
(1)字符匹配
a. 前缀树:字符串快速检索,字符串排序,最长公共前缀,自动匹配前缀显示后缀。
b. 后缀树:查找字符串s1在s2中,字符串s1在s2中出现的次数,字符串s1,s2最长公共部分,最长回文串。
c. radix tree:linux内核,nginx。
d. radix tree(patricia tree, compact prefix tree)
e. crit-bit tree(解决耗费内存问题),以及前面说的double array trie
(2)IP选路
也是前缀匹配,一定程度会用到trie

9. 跳表

跳表其实就是一种可以进行二分查找的有序链表
在这里插入图片描述

跳表的性质:
1、由很多层组成
2、每一层都是一个有序链表
3、最底层的链表包含所有元素
4、如果一个元素出现在第i层的链表中,则它在i-1层中也会出现。
5、上层节点可以跳转到下层。

Redis 中使用跳表,而不是红黑树来存储管理其中的元素(应该说的是一级元素-直接的Key,里面的value应该是有不同的数据结构)

首先,条表示SkipList 不是ZipList .ZipList 在redis中是有一个非常省内存的链表(代价是性能略低),所以在hash元素的个数很少(比如只有几十个),那么用这个结构来存储则可以性能损失很少的情况下节约很多内存(Redis 是内存数据库,能省还是要省)

在server端,对并发和性能有要求的情况下,如何选择合适的数据结构(这里是跳跃表和红黑树)。如果在单纯比价性能,跳表和红黑树可以说相差不打,但是加上并发的环境就不一样了,如果要更新数据,跳跃表需要更新的部分就比较少,锁的东西也就比较少,所以不同线程争锁的代价就相对少了,而在红黑树有个平衡的过程,牵涉到大量的节点,争锁的代价就相对高了。性能也就不如前者。在并发环境下skiplist的操作显然更加局部性一些,锁需要盯住的节点更少,因此这样的情况下性能好一些。

红黑树与B(+)树工程实现的比较:
已有的几个答案都是从算法角度分析的,我尝试分析下从工程角度区分红黑树与b+树的应用场景,红黑树一个node只存一对kv,因此可以使用类似嵌入式链表的方式实现,
数据结构本身不管理内存,比较轻量级,使用更灵活也更省内存,比如一个node可以同时存在若干个树或链表中,内核中比较常见。

而b+树由于每个node要存多对kv,node结构的内存一般就要由数据结构自己来管,是真正意义上的container,相对嵌入式方法实现的红黑树,
好处是用法简单,自己管理内存更容易做lockfree,一个node存多对kv的方式cpu cache命中率更高,所以用户态实现的高并发索引一般还是选b+树。

再说b树与b+树,btree的中间节点比b+树多存了value,同样出度的情况下,node更大,相对来说cpu cache命中率是不如b+树的。
另外再提一句,b+树的扫描特性(链表串起来的叶子节点)在无锁情况下是很难做的(我还没见到过解法),因此我目前见到的无锁b+树叶子节点都是不串起来的。

从各自特点特征角度,分析各种数据结构的应用场景:
红黑树,AVL树简单来说都是用来搜索的呗。

AVL树:平衡二叉树,一般是用平衡因子差值决定并通过旋转来实现,左右子树树高差不超过1,那么和红黑树比较它是严格的平衡二叉树,平衡条件非常严格(树高差只有1),
只要插入或删除不满足上面的条件就要通过旋转来保持平衡。由于旋转是非常耗费时间的。我们可以推出AVL树适合用于插入删除次数比较少,但查找多的情况。

红黑树:平衡二叉树,通过对任何一条从根到叶子的简单路径上各个节点的颜色进行约束,确保没有一条路径会比其他路径长2倍,因而是近似平衡的。
所以相对于严格要求平衡的AVL树来说,它的旋转保持平衡次数较少。用于搜索时,插入删除次数多的情况下我们就用红黑树来取代AVL。
(现在部分场景使用跳表来替换红黑树,可搜索“为啥 redis 使用跳表(skiplist)而不是使用 red-black?”)

B树,B+树:它们特点是一样的,是多路查找树,一般用于数据库系统中,为什么,因为它们分支多层数少呗,
都知道磁盘IO是非常耗时的,而像大量数据存储在磁盘中所以我们要有效的减少磁盘IO次数避免磁盘频繁的查找。
B+树是B树的变种树,有n棵子树的节点中含有n个关键字,每个关键字不保存数据,只用来索引,数据都保存在叶子节点。是为文件系统而生的。

Trie树:
又名单词查找树,一种树形结构,常用来操作字符串。它是不同字符串的相同前缀只保存一份。
相对直接保存字符串肯定是节省空间的,但是它保存大量字符串时会很耗费内存(是内存)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

phial03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值