红黑树、B(+)树、跳表、AVL等数据结构,应用场景及分析,以及一些英文缩写

在网上学习了一些材料。

这一篇:https://www.zhihu.com/question/30527705

AVL树:最早的平衡二叉树之一。应用相对其他数据结构比较少。windows对进程地址空间的管理用到了AVL树

红黑树:平衡二叉树,广泛用在C++的STL中。map和set都是用红黑树实现的。我们熟悉的STL的map容器底层是RBtree,当然指的不是unordered_map,后者是hash。

B/B+树用在磁盘文件组织 数据索引和数据库索引

Trie树 字典树,用在统计和排序大量字符串

------

AVL是一种高度平衡的二叉树,所以通常的结果是,维护这种高度平衡所付出的代价比从中获得的效率收益还大,故而实际的应用不多,更多的地方是用追求局部而不是非常严格整体平衡的红黑树。当然,如果场景中对插入删除不频繁,只是对查找特别有要求,AVL还是优于红黑的。

红黑树的应用就很多了,除了上面同学提到的STL,还有
epoll在内核中的实现,用红黑树管理事件块
nginx中,用红黑树管理timer等
Java的TreeMap实现
著名的linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块

B和B+主要用在文件系统以及数据库中做索引等,比如Mysql:B-Tree Index in MySql

trie 树的一个典型应用是前缀匹配,比如下面这个很常见的场景,在我们输入时,搜索引擎会给予提示
还有比如IP选路,也是前缀匹配,一定程度会用到trie

------

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

首先,跳表是skiplist?不是ziplist。ziplist在redis中是一个非常省内存的链表(代价是性能略低),所以在hash元素的个数很少(比如只有几十个),那么用这个结构来存储则可以在性能损失很小的情况下节约很多内存(redis是内存数据库啊,能省还是要省的)。好这个问题清楚了。

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

另外Redis作者描述的使用跳表的原因:

请看开发者说的,他为什么选用skiplist The Skip list

There are a few reasons:
1) They are not very memory intensive. It‘s up to you basically. Changing parameters about the probability of a node to have a given number of levels will make then less memory intensive than btrees.注:跳表的一个缺点是耗内存(因为要重复分层存节点),但是作者也说了,可以调参数来降低内存消耗,和那些平衡树结构达到差不多。
2) A sorted set is often target of many ZRANGE or ZREVRANGE operations, that is, traversing the skip list as a linked list. With this operation the cache locality of skip lists is at least as good as with other kind of balanced trees.注:redis经查有范围操作,这样利用跳表里面的双向链表,可以方便地操作。另外还有缓存区域化(cache locality)不会比平衡树差。
3) They are simpler to implement, debug, and so forth. For instance thanks to the skip list simplicity I received a patch (already in Redis master) with augmented skip lists implementing ZRANK in O(log(N)). It required little changes to the code.注:实现简单。zrank操作能够到O(log(N)).
About the Append Only durability & speed, I don‘t think it is a good idea to optimize Redis at cost of more code and more complexity for a use case that IMHO should be rare for the Redis target (fsync() at every command). Almost no one is using this feature even with ACID SQL databases, as the performance hint is big anyway.
About threads: our experience shows that Redis is mostly I/O bound. I‘m using threads to serve things from Virtual Memory. The long term solution to exploit all the cores, assuming your link is so fast that you can saturate a single core, is running multiple instances of Redis (no locks, almost fully scalable linearly with number of cores), and using the "Redis Cluster" solution that I plan to develop in the future.

上面文章中有一些英文缩写,整理如下:

imho, imo(in my humble opinion, in my opinion):在我看来,常见于论坛。

idk(I don’t know):我不知道。

rofl(rolling on the floor laughing):笑到摔到地上。

roflmao(rolling on the floor laughing my ass of):前两个的结合版,也就是超级搞笑的意思。

sth(something):某事某物。

nth(nothing):什么也没有。

plz(please):请。please 字尾是z 音,所以按照读音缩写为plz。

thx(thanks):谢谢。按照发音来看,thanks字尾的ks可以用字母X代替。

红黑树与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树:
又名单词查找树,一种树形结构,常用来操作字符串。它是不同字符串的相同前缀只保存一份。
相对直接保存字符串肯定是节省空间的,但是它保存大量字符串时会很耗费内存(是内存)。
类似的有
前缀树(prefix tree),后缀树(suffix tree),radix tree(patricia tree, compact prefix tree),crit-bit tree(解决耗费内存问题),以及前面说的double array trie。
简单的补充下我了解应用
前缀树:字符串快速检索,字符串排序,最长公共前缀,自动匹配前缀显示后缀。
后缀树:查找字符串s1在s2中,字符串s1在s2中出现的次数,字符串s1,s2最长公共部分,最长回文串。
radix tree:linux内核,nginx。

红黑树的介绍可以看这两篇文章:史上最清晰的红黑树讲解(上)+(下)

http://mt.sohu.com/20161014/n470317653.shtml

http://mt.sohu.com/20161018/n470610910.shtml

当查找树的结构发生改变时,红黑树的条件可能被破坏,需要通过调整使得查找树重新满足红黑树的条件。
调整可以分为两类:
一类是颜色调整,即改变某个节点的颜色;
另一类是结构调整,集改变检索树的结构关系。结构调整过程包含两个基本操作:左旋(Rotate Left),右旋(RotateRight)

记住,无论有多少情况,具体的调整操作只有两种:1.改变某些节点的颜色,2.对某些节点进行旋转。

另开一文分析字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树。

时间: 2024-12-16 14:27:04

红黑树、B(+)树、跳表、AVL等数据结构,应用场景及分析,以及一些英文缩写的相关文章

从hihttps开源waf教你红黑树和哈希表的不同

哈希和红黑树的详细教程很多,但初学者往往云里雾里,不知道实战项目该用谁,今天笔者就从结合hihttps这个开源waf的源码,从网络安全角度来对比一下哈希数据结构和红黑树的应用场景.hihttps是一款基于MQTT的免费的物联网防火墙,同时也是web应用防火墙,既支持传统的检测功能如SQL注入.XSS.恶意漏洞扫描.密码破解.CC.DDOS等),又支持无监督机器学习,抗.首先github上下载源码,https://github.com/qq4108863/himqtt ,在src\waf目录有ha

浅谈AVL树,红黑树,B树,B+树原理及应用

背景:这几天在看<高性能Mysql>,在看到创建高性能的索引,书上说mysql的存储引擎InnoDB采用的索引类型是B+Tree,那么,大家有没有产生这样一个疑问,对于数据索引,为什么要使用B+Tree这种数据结构,和其它树相比,它能体现的优点在哪里? 看完这篇文章你就会了解到这些数据结构的原理以及它们各自的应用场景. 二叉查找树 简介 二叉查找树也称为有序二叉查找树,满足二叉查找树的一般性质,是指一棵空树具有如下性质: 任意节点左子树不为空,则左子树的值均小于根节点的值. 任意节点右子树不为

红黑树(RB-tree)比AVL树的优势在哪?

1. 如果插入一个node引起了树的不平衡,AVL和RB-Tree都是最多只需要2次旋转操作,即两者都是O(1):但是在删除node引起树的不平衡时,最坏情况下,AVL需要维护从被删node到root这条路径上所有node的平衡性,因此需要旋转的量级O(logN),而RB-Tree最多只需3次旋转,只需要O(1)的复杂度. 2. 其次,AVL的结构相较RB-Tree来说更为平衡,在插入和删除node更容易引起Tree的unbalance,因此在大量数据需要插入或者删除时,AVL需要rebalan

红黑树/B+树/AVL树

RB Tree 红黑树  :http://blog.csdn.net/very_2/article/details/5722682 AVL Tree    :http://blog.csdn.net/collonn/article/details/20128205 B[+/-] Tree  :http://hxraid.iteye.com/blog/611105 几种Tree 总结对比 :http://www.iteye.com/topic/614070 [nginx模块开发与架构解析]

红黑树和哈希表的对比

什么是Hash Hash,也可以称为"散列",就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值.这是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出(也就是多对一的关系). 哈希表的构造 在所有的线性数据结构中,数组的定位速度最快,因为它可通过数组下标直接定位到相应的数组空间,就不需要一个个查找.而哈希表就是利用数组这个能够快速定位数据的结构解决以上的问题的. "数组可以通过下标直接定位到相应的空间"

霍夫曼树 二三树 红黑树 B树 B+树

霍夫曼树: 特点:带权路径长度最短,∑(每个节点的权重)*(每个节点的层数) 生成:每次合并权值最小的两个节点(子树)建立二叉树,将合并后的子树作为新节点,权值为节点(子树)权值之和 二三树: 特点:平衡查找树,每个叶子节点为空且层数相同,查找时间复杂度O(lgn) 生成:2节点包含一个key和两个子节点(left->key<key<right->key),3节点包含两个key和三个子节点(left->key<key1<middle->key<key2

红黑树和AVL树的比较

1. 红黑树并不追求"完全平衡"--它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能. 红黑树能够以O(log2 n) 的时间复杂度进行搜索.插入.删除操作.此外,由于它的设计,任何不平衡都会在三次旋转之内解决.当然,还有一些更好的,但实现起来更复杂的数据结构,能够做到一步旋转之内达到平衡,但红黑树能够给我们一个比较"便宜"的解决方案.红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高. 当然,红黑树并不适应所有应用树的领域.如果数据基本上是

红黑树与AVL树

概述:本文从排序二叉树作为引子,讲解了红黑树,最后把红黑树和AVL树做了一个比较全面的对比. 1 排序二叉树 排序二叉树是一种特殊结构的二叉树,可以非常方便地对树中所有节点进行排序和检索. 排序二叉树要么是一棵空二叉树,要么是具有下列性质的二叉树: ? 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值: ? 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值: ? 它的左.右子树也分别为排序二叉树. 下图显示了一棵排序二叉树: 对排序二叉树,若按中序遍历就可以得到由小到大的

B树、B+树、红黑树、AVL树

定义及概念 B树 二叉树的深度较大,在查找时会造成I/O读写频繁,查询效率低下,所以引入了多叉树的结构,也就是B树.阶为M的B树具有以下性质: 1.根节点在不为叶子节点的情况下儿子数为 2 ~ M2.除根结点以外的非叶子结点的儿子数为 M/2(向上取整) ~ M3.拥有 K 个孩子的非叶子节点包含 k-1 个keys(关键字),且递增排列4.所有叶子结点在同一层,即深度相同 (叶节点可以看成是一种外部节点,不包含任何关键字信息) 在B-树中,每个结点中关键字从小到大排列,并且当该结点的孩子是非叶

[数据结构]二叉搜索树(BST) VS 平衡二叉排序树(AVL) VS B树(平衡多路搜索树) VS B+树 VS 红黑树(平衡二叉B树)

1 二叉排序树/二叉查找树/Binary Sort Tree 1种对排序和查找都很有用的特殊二叉树 叉排序树的弊端的解决方案:平衡二叉树 二叉排序树必须满足的3条性质(或是具有如下特征的二叉树) 若它的左子树不为空,则:左子树上所有结点的值< 它根结点的值 若它的右子树不为空,则:右子树上所有结点的值 > 它根结点的值 它的左子树.右子树也分别为二叉排序树(递归性) (按照如上定义,即: 1 无键值相等的结点 2 中序遍历一颗二叉树时,可得一个结点值递增的有序序列) 2 平衡二叉排序树/Bal