`

跳跃表的应用-redis

阅读更多
为什么选择跳表
目前经常使用的平衡数据结构有:B树,红黑树,AVL树,Splay Tree, Treep等。
想象一下,给你一张草稿纸,一只笔,一个编辑器,你能立即实现一颗红黑树,或者AVL树
出来吗? 很难吧,这需要时间,要考虑很多细节,要参考一堆算法与数据结构之类的树,
还要参考网上的代码,相当麻烦。
用跳表吧,跳表是一种随机化的数据结构,目前开源软件 Redis 和 LevelDB 都有用到它,
它的效率和红黑树以及 AVL 树不相上下,但跳表的原理相当简单,只要你能熟练操作链表,
就能轻松实现一个 SkipList。
有序表的搜索
考虑一个有序表:
clip_image001
从该有序表中搜索元素 < 23, 43, 59 > ,需要比较的次数分别为 < 2, 4, 6 >,总共比较的次数
为 2 + 4 + 6 = 12 次。有没有优化的算法吗?  链表是有序的,但不能使用二分查找。类似二叉
搜索树,我们把一些节点提取出来,作为索引。得到如下结构:
clip_image002
这里我们把 < 14, 34, 50, 72 > 提取出来作为一级索引,这样搜索的时候就可以减少比较次数了。
我们还可以再从一级索引提取一些元素出来,作为二级索引,变成如下结构:
clip_image003
这里元素不多,体现不出优势,如果元素足够多,这种索引结构就能体现出优势来了。
这基本上就是跳表的核心思想,其实也是一种通过“空间来换取时间”的一个算法,通过在每个节点中增加了向前的指针,从而提升查找的效率。
跳表
下面的结构是就是跳表:
其中 -1 表示 INT_MIN, 链表的最小值,1 表示 INT_MAX,链表的最大值。
clip_image005
跳表具有如下性质:
(1) 由很多层结构组成
(2) 每一层都是一个有序的链表
(3) 最底层(Level 1)的链表包含所有元素
(4) 如果一个元素出现在 Level i 的链表中,则它在 Level i 之下的链表也都会出现。
(5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。
跳表的搜索
clip_image007
例子:查找元素 117
(1) 比较 21, 比 21 大,往后面找
(2) 比较 37,   比 37大,比链表最大值小,从 37 的下面一层开始找
(3) 比较 71,  比 71 大,比链表最大值小,从 71 的下面一层开始找
(4) 比较 85, 比 85 大,从后面找
(5) 比较 117, 等于 117, 找到了节点。
具体的搜索算法如下:
C代码clip_image009
1.
3. find(x) 
4. {
5.     p = top;
6. while (1) {
7. while (p->next->key < x)
8.             p = p->next;
9. if (p->down == NULL) 
10. return p->next;
11.         p = p->down;
12.     }
13. }
跳表的插入
先确定该元素要占据的层数 K(采用丢硬币的方式,这完全是随机的)
然后在 Level 1 ... Level K 各个层的链表都插入元素。
例子:插入 119, K = 2
clip_image011
如果 K 大于链表的层数,则要添加新的层。
例子:插入 119, K = 4
clip_image013
丢硬币决定 K
插入元素的时候,元素所占有的层数完全是随机的,通过一下随机算法产生:
C代码clip_image009[1]
1. int random_level()
2. {
3.     K = 1;
4.
5. while (random(0,1))
6.         K++;
7.
8. return K;
9. }
相当与做一次丢硬币的实验,如果遇到正面,继续丢,遇到反面,则停止,
用实验中丢硬币的次数 K 作为元素占有的层数。显然随机变量 K 满足参数为 p = 1/2 的几何分布,
K 的期望值 E[K] = 1/p = 2. 就是说,各个元素的层数,期望值是 2 层。
跳表的高度。
n 个元素的跳表,每个元素插入的时候都要做一次实验,用来决定元素占据的层数 K,
跳表的高度等于这 n 次实验中产生的最大 K,待续。。。
跳表的空间复杂度分析
根据上面的分析,每个元素的期望高度为 2, 一个大小为 n 的跳表,其节点数目的
期望值是 2n。
跳表的删除
在各个层中找到包含 x 的节点,使用标准的 delete from list 方法删除该节点。
例子:删除 71
clip_image015
分享到:
评论

相关推荐

    linux-redis

    为了提高读写效率,Redis还提供了多种数据结构优化手段,如压缩表、字典的负载因子调整、跳跃表等。此外,Redis支持主从复制,可以创建多个从节点来分摊读取压力,实现高可用性。当主节点出现故障时,可以自动或手动...

    Redis学习笔记

    "深入redis学习(九)--redis skiplist.doc"讲解了跳跃表,这是Redis实现有序集合排序的底层数据结构,提供O(log N)的查找、插入和删除效率,比红黑树更节省内存。 "深入redis学习(十)--redis object management....

    Redis_Source_code:Redis源码分析-redis source code

    -有序集合:元素有序且不重复,使用跳跃表(Skip List)实现,支持范围查询。 2. Redis的核心组件: - Redis服务器:处理客户端连接,解析命令,执行操作并返回结果。 - RDB持久化:定期将内存中的数据快照到...

    redis-6.2.1-win64.7z

    它改进了对某些数据结构的操作效率,如哈希表和跳跃列表。此外,此版本还引入了对TLS(Transport Layer Security)的支持,增强了安全性,允许在不安全的网络环境中提供加密的数据传输。 2. **msys2 编译环境**: ...

    Redis-x64-3

    2. **有序集合的跳跃列表实现**:在3.2版本之前,有序集合(Sorted Set)使用了哈希表和跳跃表的混合结构,而3.2版本开始完全使用跳跃表,这提高了插入、删除和范围查询的性能。 3. **Lua脚本的改进**:Redis支持...

    redis_介绍_-_田琪

    - **有序集合(Sorted Set)**:有序的集合,元素带分数,内部使用哈希表和跳跃列表(skiplist)进行排序,通过`ZADD`、`ZRANGE`命令操作。 2. **持久化与复制** - **持久化**:Redis 支持两种持久化方式,分别是快照...

    一个简单的跳跃表实现,附有详细注释

    本篇将详细介绍跳跃表的原理、实现及其在Redis中的应用。 跳跃表由一系列层构成,每一层都是一个有序链表。从底层到顶层,链表中的节点数量逐渐减少,但跨度增加。最底层的链表包含所有元素,而顶层的链表可能只...

    算法文档无代码浅谈跳跃表的相关操作及其应用

    - 数据库索引:某些数据库系统(如Redis的有序集合)会使用跳跃表来实现索引,因为它们提供快速的查找性能。 - 负载均衡:在分布式系统中,跳跃表可用来存储服务器节点,便于快速选择处理能力和负载较低的服务器来...

    redis_reading:阅读redis 3.0.1的源代码-redis source code

    1. 数据结构:Redis的核心数据结构包括 SDS (Simple Dynamic String)、链表(list)、哈希表(dict)、跳跃表(zskiplist)和整数集合(intset)。SDS是Redis自定义的字符串实现,相比C语言的原始字符串,它更高效且...

    Redis实践与总结

    - **Skiplist**:对于更大规模的数据,Redis采用Skiplist(跳跃表)进行编码,这是一种随机化数据结构,通过在每个节点中维护多个指向其他节点的指针,达到快速访问节点的目的。跳跃表的平均时间复杂度为O(log N),...

    跳跃表skiplist参考文档

    本篇将深入探讨跳跃表的基本概念、工作原理以及其在Redis中的应用。 ### 跃表的概念 跳跃表是由William Pugh于1989年提出的,它是一种随机化的数据结构,主要用于实现高效查找、插入和删除操作。与传统的平衡树如...

    windows版本redis3.2

    2. **有序集合跳跃表**:引入跳跃表(Skip List)作为有序集合的底层实现,提升了查询性能,同时降低了内存使用。 3. **LUA脚本错误处理**:支持在LUA脚本中抛出错误,增强了脚本调试能力。 4. **发布/订阅增强**:...

    Redis中文手册

    - **跳跃表的应用**:跳跃表在Redis中用于实现有序集合数据类型,支持元素的快速查找、插入和删除操作。 - **小结**:跳跃表结合了链表和二叉搜索树的优点,为Redis提供了高效的有序集合管理。 #### 二、内存映射...

    redis操作源代码以及查看redis的情况的辅助代码以及redis安装包

    2. **数据结构**:Redis内部使用高效的数据结构,如哈希表、链表、跳跃表和压缩树等,源代码可以帮助理解这些数据结构的实现细节。 3. **事务处理**:Redis支持单个命令或多个命令的原子性执行,源代码中可能包括...

    redis-02.pdf

    6. **跳跃表(Skip List)**:跳跃表用于高效地查找元素,支持平均O(logN)、最坏O(N)的时间复杂度。跳跃表在数据插入时会更新表结构,分为查找插入点、新建插入点和修改节点指针三步。 7. **过期时间与缓存策略**:...

    Redis Windows源码

    例如,链表、跳跃表(用于有序集合的快速查找)和压缩表(用于节省内存)等都是Redis内部的重要组件。 3. 源码编译与配置: 要在Windows上编译Redis源码,首先需要安装GCC编译器(如MinGW)和make工具。然后,使用...

    redis3源码及解析

    2. 跳跃表(Skip List):Redis使用跳跃表来实现有序集合的高效查找。跳跃表是一种随机化数据结构,通过多层索引来加速查找过程,性能接近于平衡二叉搜索树,但实现起来更简单。 3. 哈希表(Hash Table):Redis的...

    redis必备书籍

    - **用途:** 跳跃表允许 Redis 以 O(log N) 的时间复杂度进行成员的查找、插入和删除操作。 - **特点:** 与平衡二叉树相比,跳跃表更容易实现并且具有更好的性能表现。 #### 二、内存映射数据结构 **2.1 整数集合*...

    Redis介绍与实现(公司内部请培训机构的课件)

    - **启动与检查**:使用`redis-server`启动Redis服务,使用`redis-cli`检查Redis是否正在运行。 - **字符串类型**:`SET`用于设置键值对,`GET`用于获取键对应的值,`INCR`和`DECR`分别用于增加或减少数值。 - **...

Global site tag (gtag.js) - Google Analytics