SkipList 跳跃表

简介: 引子考虑一个有序表:14->23->34->43->50->59->66->72从该有序表中搜索元素 < 23, 43, 59 > ,需要比较的次数分别为 < 2, 4, 6 >,总共比较的次数为 2 + 4 + 6 = 12 次。

 

引子

考虑一个有序表:14->23->34->43->50->59->66->72

从该有序表中搜索元素 < 23, 43, 59 > ,需要比较的次数分别为 < 2, 4, 6 >,总共比较的次数

为 2 + 4 + 6 = 12 次。有没有优化的算法吗?  链表是有序的,但不能使用二分查找。类似二叉

搜索树,我们把一些节点提取出来,作为索引。

这里我们把 < 14, 34, 50, 72 > 提取出来作为一级索引,这样搜索的时候就可以减少比较次数了。

我们还可以再从一级索引提取一些元素出来,作为二级索引,变成如下结构:

如果元素足够多,这种索引结构就能体现出优势来了。

 

跳跃表 

跳表具有如下性质:

(1) 由很多层结构组成

(2) 每一层都是一个有序的链表

(3) 最底层(Level 1)的链表包含所有元素

(4) 如果一个元素出现在 Level i 的链表中,则它在 Level i 之下的链表也都会出现。

(5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

其中 -1 表示 INT_MIN, 链表的最小值,1 表示 INT_MAX,链表的最大值。

跳跃表的搜索

例子:查找元素 117

(1) 比较 21, 比 21 大,往后面找

(2) 比较 37,   比 37大,比链表最大值小,从 37 的下面一层开始找

(3) 比较 71,  比 71 大,比链表最大值小,从 71 的下面一层开始找

(4) 比较 85, 比 85 大,从后面找

(5) 比较 117, 等于 117, 找到了节点。

跳跃表的插入

  1. 新节点和各层索引节点逐一比较,确定原链表的插入位置。O(logN)

  2. 把索引插入到原链表。O(1)

  3. 利用抛硬币的随机方式,决定新节点是否提升为上一级索引。结果为“正”则提升并继续抛硬币,结果为“负”则停止。O(logN)

总体上,跳跃表插入操作的时间复杂度是O(logN),而这种数据结构所占空间是2N,既空间复杂度是 O(N)。 

跳跃表的删除

  1. 自上而下,查找第一次出现节点的索引,并逐层找到每一层对应的节点。O(logN) 

  2. 删除每一层查找到的节点,如果该层只剩下1个节点,删除整个一层(原链表除外)。O(logN)

总体上,跳跃表删除操作的时间复杂度是O(logN)。

 

总结 

跳跃表的优点在维持结构平衡的成本比较的,根据扔硬币,所以完全依靠随机。而二叉查找树在多次插入删除后,需要Rebalance来重新调整结构平衡。 

 

目录
相关文章
|
2月前
|
NoSQL 算法 Java
数据结构之跳表理解
数据结构之跳表理解
55 0
|
3月前
|
NoSQL Redis C++
平衡二叉树、跳跃表
平衡二叉树、跳跃表
|
3月前
|
存储 NoSQL Redis
Redis数据结构之——跳表skiplist
Redis数据结构之——跳表skiplist
|
9月前
|
存储 NoSQL 算法
跳表
跳表
78 0
|
7月前
|
存储 NoSQL 算法
Redis中ZSet的底层数据结构跳跃表skiplist,你真的了解吗?
Redis中ZSet的底层数据结构跳跃表skiplist,你真的了解吗?
|
9月前
|
存储 数据库 索引
跳表问题的探讨
跳表是一种高效的数据结构,它可以在有序链表上进行快速的搜索、插入、删除操作,时间复杂度为O(log n)。本文将介绍跳表的原理、实现方式以及其在实际应用中的优势和局限性。
80 0
|
10月前
|
NoSQL Redis 索引
【数据结构】跳表
【数据结构】跳表
52 0
|
存储 算法 NoSQL
常见数据结构-跳表
常见数据结构-跳表
|
存储 缓存 算法
那些年,散列表和链表的混合双打
那些年,散列表和链表的混合双打
288 0
那些年,散列表和链表的混合双打
|
NoSQL Redis
跳跃表介绍
有序集合在生活中比较常见,例如根据成绩对学生排名,根据得分对玩家排名等。对于有序集合的底层实现,可以用数组、平衡树、链表等。数组不便元素的插入、删除;平衡树或红黑树虽然效率高但结构复杂;链表查询需要遍历所有效率低。
跳跃表介绍