首页
学习
活动
专区
圈层
工具
发布
    • 综合排序
    • 最热优先
    • 最新优先
    时间不限
  • 来自专栏阿伟的个人博客

    跳表

    增加了向前指针的链表叫作跳表跳表全称叫做跳跃表,简称跳表跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。 对于第二层首先发现一个结点为3,小于4,继续后移,发现下一个结点为5,因此第二层插入到3后面。 对于第一层,发现3的下一个结点为5,大于4,插入3后面即可。 还是以该跳表为例,若我们待删除的元素为3。 第四层,当前结点的下一个位置是5,不为3,下移 第三层,当前结点的下一个位置是5,不为3,下移 第二层,当前结点的下一个位置是3,删除其下一个位置,下移 第一层,当前结点的下一个位置为2小于三,右移,当前位置的下一个元素为 3,删除其下一个元素。

    53930发布于 2020-08-12
  • 来自专栏机械之心

    跳表

    # 跳表 # 什么是跳表 对于一个有序数组,可以使用高效的二分查找法,其时间复杂度为 O(log n) 。 但是,即使是有序的链表,也只能使用低效的顺序查找,其时间复杂度为 O(n) 。 这种链表加多级索引的结构,就是跳表。 所以跳表查询数据的时间复杂度就是 O(logn) 。 # 跳表的空间复杂度 比起单纯的单链表,跳表需要存储多级索引,肯定要消耗更多的存储空间。 # 跳表索引动态更新 当我们不停地往跳表中插入数据时,如果我们不更新索引,就有可能出现某 2 个索引结点之间数据非常多的情况。极端情况下,跳表还会退化成单链表。 # 为什么需要跳表 跳表是一种动态数据结构,支持快速的插入、删除、查找操作,时间复杂度都是 O(logn) 。 跳表的空间复杂度是 O(n) 。

    50620编辑于 2023-04-07
  • 来自专栏程序猿~

    跳表 - skipList

    简介 SkipList(跳表)这种数据结构是由William Pugh于1990年在在 Communications of the ACM June 1990, 33(6) 668-676 发表了Skip String> concurrentSkipListSet = new ConcurrentSkipListSet<>(); 2.Redis Redis当中的Sorted-set这种有序的集合,正是对于跳表的改进和应用 3.Google的著名项目Bigtable 跳表java实现 版本1 public class SkipList{ //结点“晋升”的概率 private static final double System.out.println(); } //链表结点类 public class Node { public int data; //跳表结点的前后和上下都有指针 list.printList(); list.search(50); list.remove(50); list.search(50); } } 参考 漫画:什么是 “跳表

    63030发布于 2020-08-27
  • 来自专栏C/C++、数据结构、算法

    DS高阶:跳表

    一般跳表会设计一个最大层数maxLevel的限制,其次会设置一个多增加一层的概率p。 时间复杂度:logN 具体的分析可以看下面的文章:Redis内部数据结构详解(6)——skiplist 2、skiplist的模拟实现 力扣有一道设计跳表的题. - 力扣(LeetCode)设计跳表 1、如果你为空,或者我比你小,那就得往下走 ->--level 2、如果我比你大,就可以直接跳到你的位置->更新cur=cur->_nextV[level] 3、如果找到了就返回true,如果循环结束了都找不到

    28500编辑于 2024-05-26
  • 来自专栏山行AI

    浅析skiplist(跳表)

    skiplist(跳表)的应用场景 1. 跳表 1. 结构 跳表由William Pugh 1989年发明。 引用自:https://en.wikipedia.org/wiki/Skip_list 跳表是一个“概率型”的数据结构,在很多应用场景中可以替代平衡树。 3. 跳表特性 一个普通的有序链表: ? 如果从上面的列表中查找23需要遍历4次,查找59时需要遍历6次。而对这个链表,我们没法使用二分查找。 于是我们对数据节点加上一级索引如下图: ? 相比于二叉查找树,跳表维持结构平衡的成本比较低,完全靠随机。而二叉查找树需要Rebalance来重新调整平衡的结构。

    2.8K40发布于 2019-06-28
  • 来自专栏慕枫技术笔记

    这玩意叫跳表

    跳表介绍 跳表结构 在说明跳表数据结构特点之前,我们先来回顾下链表的数据结构。 length; //跳表长度 int level; //跳表的层级 } zskiplist; 上文中我们提到过跳表的本质是具备多级索引的链表,因此只要知道了头节点或者尾节点就可以访问整个跳表数据了 另外跳表长度表示跳表中包含的跳表节点数,而level则表示跳表拥有多少层检索索引。 了解了跳表的结构之后,我们在深入看下跳表中的节点是怎样的结构,如下所示: //跳表节点结构体 typedef struct zskiplistNode { //跳表元素 sds ele; Redis中跳表的数据检索流程大致如下: 总结 本文主要对跳表这个不常用的数据结构进行了介绍,同时分析了二分查找思想在跳表中的应用,重点阐述了跳表的数据结构特征。

    60610编辑于 2023-03-20
  • 来自专栏C++&linux

    【数据结构】跳表

    一、跳表是什么? 1. 3. 设计跳表 1. 在实现跳表的时候,一定要对照着图来实现,如果纯靠脑子,很容易把某些特殊情况给遗漏掉,至于图的话,就拿跳表论文里面的这个图就可以,这个图画的是最板正的。 跳表与AVL树,红黑树相比,在时间复杂度上两者都非常的优秀,同时也都能够做到遍历数据有序,但跳表的空间复杂度更优秀一些,平衡树的每个结点都会存储3个指针,同时还有平衡因子/颜色的空间消耗,拿redis中的跳表为例 跳表与哈希表相比,在时间复杂度上来说,哈希表会更优秀,因为他的时间复杂度是O(1),所以在时间复杂度上跳表的优势并不明显,但跳表可以做到遍历数据有序,而哈希表却做不到这一点。

    54810编辑于 2024-02-23
  • 来自专栏用户4352451的专栏

    跳跃表(跳表

    最高的层的索引层的长度为2,那我们计算出 层级为 k = log2^n- 1 ,如果我们每一层遍历M个元素那么我们的时间复杂度为O(m(log2^n-1)) ,我们的是两个元素结合为一个节点那么每一层最多遍历3个元素 ,那么我们时间复杂度为O(3log2^n -1) 那么时间复杂度为 O(logn) 现在就是在原有的得单链表上创建了多层索引而达到二分法查找,达到很高。

    59320发布于 2020-08-26
  • 来自专栏JMCui

    跳表(SkipList) 和 ConcurrentSkipListMap

    一、跳表(SkipList) 对于单链表,即使链表是有序的,如果想要在其中查找某个数据,也只能从头到尾遍历链表,这样效率自然就会很低,跳表就不一样了。 就查询的性能而言,跳表的时间复杂度是 O(logn)。 跳表的本质,其实是同时维护了多个链表,并且链表是分层的: ? 其中最低层的链表,维护了跳表内所有的元素,每往上一层链表,都是下面一层的子集。 跳表内每一层链表的元素都是有序的。查找时,可以从顶级链表开始找。 从上面很容易看出,跳表是一种利用空间换时间的算法。 具体的源码分析可以参见这篇文章:https://www.jianshu.com/p/2075a76a43a3 四、ConcurrentSkipListMap 示例 下面是 “多个线程同时操作并且遍历 map

    1.3K20发布于 2020-03-19
  • 来自专栏叽叽西

    数据结构-跳表

    按照前面这种索引结构,我们每一级索引都最多只需要遍历 3 个结点,也就是说 m=3,为什么是 3 呢?我来解释一下。 在第 k-1 级索引中,y 和 z 之间只有 3 个结点(包含 y 和 z),所以,我们在 K-1 级索引中最多只需要遍历 3 个结点,依次类推,每一级索引都最多只需要遍历 3 个结点。 通过上面的分析,我们得到 m=3,所以在跳表中查询任意数据的时间复杂度就是 O(logn)。这个查找的时间复杂度跟二分查找是一样的。换句话说,我们其实是基于单链表实现了二分查找,是不是很神奇? 通过等比数列求和公式,总的索引结点大约就是 n/3+n/9+n/27+...+9+3+1=n/2。 跳表索引动态更新 跳表索引动态更新当我们不停地往跳表中插入数据时,如果我们不更新索引,就有可能出现某 2 个索引结点之间数据非常多的情况。极端情况下,跳表还会退化成单链表。

    53010编辑于 2022-05-17
  • 来自专栏Michael阿明学习之路

    数据结构--跳表SkipList

    对单链表查找一个元素的时间复杂度是 O(n) 通过对链表建立多级索引的结构,就是跳表,查找任意数据、插入数据、删除数据的时间复杂度均为 O(log n) 前提:建立了索引,用空间换时间的思路 (每两个节点建立一个索引 skiplist.h /** * @description: 跳表 * @author: michael ming * @date: 2019/4/22 22:21 * @modified by unsigned int UINT; template <class T> class skipNode { public: T data; skipNode<T> **next; //跳表节点的 << endl; } } }; #endif //SKIPLIST_SKIPLIST_H test_skiplist.cpp /** * @description: 测试跳表

    41320发布于 2021-02-20
  • 来自专栏程序员小灰

    漫画:什么是 “跳表” ?

    假设我们要插入的结点是10,首先我们按照跳表查找结点的方法,找到待插入结点的前置结点(仅小于待插入结点): 接下来,按照一般链表的插入方式,把结点10插入到结点9的下一个位置: 这样是不是插入工作就完成了呢 假设我们要从跳表中删除结点10,首先我们按照跳表查找结点的方法,找到待删除的结点: 接下来,按照一般链表的删除方式,把结点10从原始链表当中删除: 这样是不是删除工作就完成了呢?并不是。 我们需要顺藤摸瓜,把索引当中的对应结点也一一删除: 刚才的例子当中,第3层索引的结点已经没有了,因此我们把整个第3层删去: 最终的删除结果如下: 1. 程序中跳表采用的是双向链表,无论前后结点还是上下结点,都各有两个指针相互指向彼此。 2. 程序中跳表的每一层首位各有一个空结点,左侧的空节点是负无穷大,右侧的空节点是正无穷大。 代码中的跳表就像下图这样: public class SkipList{ //结点“晋升”的概率 private static final double PROMOTE_RATE =

    85760发布于 2020-08-27
  • 来自专栏皮皮星球

    golang实现跳表(SkipList)

    跳表的理解 如果要维护一组有序的整数序列,支持高效的插入删除和搜索,并且能维护序列的有序性。可以选择的数据结构是有限的,哈希表虽然支持常数时间复杂度的增删查,但是hashmap不能维护有序性。 跳表这种数据结构利用空间换时间,性能和红黑树比肩,还能支持区间搜索,在redis和leveldb等开源项目中都用被应用。 跳表的结构如图所示: image.png 在最底层包含了所有的数据节点,每一层链表都有一个指向下一层和自己相同的节点,向后的指针指向随机的同一层比自己大的数据。 logn,如果每一层都需要遍历m个节点,那么在跳表中查询某个数的时间复杂度就是O(m * log(n))。 简单的单向跳表实现: skiplist

    1.5K10发布于 2020-09-23
  • 来自专栏算法之名

    ConcurrentSkipListMap跳表原理解析

    内部结构如下(图片来源于网络),这里面Node其实就是HeadIndex中的level1,level2,level3中的一个个绿点。 ? //竞争成功的,退出'for (;;)'循环 break outer; } } //到此时表示已经节点已经put成功了,但对于跳表来说 level <= (max = h.level)) { //根据层数level不断创建新增节点的下层索引 //注意此时只是新增了新节点的索引,并没有关联到跳表的真实体中 比方说我们要在这个图中找55,它是不会直接在L3中直接找到的,而是经过箭头的方向在L1找55的前置节点。 for (;;) { //获取原始头索引以及该头索引的链表后续索引,当ConcurrentSkipListMap刚初始化的时候,r为null //但是我们查找肯定不会在空的跳表中查找

    67110发布于 2019-12-03
  • 来自专栏小明说Java

    Redis压缩列表和跳表

    Redis 的压缩列表(ziplist)和跳表(skiplist)是两种不同的数据结构,它们在 Redis 中被用于实现不同的功能。压缩列表实际上类似于一个数组,数组中的每一个元素都对应保存一个数据。 跳表(skiplist)有序链表只能逐一查找元素,导致操作起来非常缓慢,于是就出现了跳表,时间复杂度为O(N)。 具体来说,跳表,在链表的基础上,增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位,如下图所示:如果我们要在链表中查找33这个元素,只能从头开始遍历链表,查找6次,直到找到33为止。 这样,我们只需要3次查找,就能定位到元素33了。可以看到,这个查找过程就是在多级索引上跳来跳去,最后定位到元素。这也正好符合“跳”表的叫法。当数据量很大时,跳表的查找复杂度就是O(logN)。 总之,压缩列表和跳表是两种不同的数据结构,它们在 Redis 中被用于实现不同的功能。压缩列表用于存储短的列表或集合,而跳表用于实现可以在对数时间内进行搜索、插入和删除操作的有序集合。

    1.2K10编辑于 2023-11-21
  • 来自专栏Redis源码学习系列

    Redis源码学习之跳表

    score,以及每个节点的层数结构,每层都包含着前进指针与跨度;除此之外,每个节点还包含一个后退指针,假设跳表只有一层,那么整个跳表将退化为双端链表。 跳表,持有跳表的结构包括指向跳表表头和表尾的指针,以及整个跳表的长度(即第一层的节点数,但不包含头结点),还有整个跳表最高层的层数。 数组如图中所示,我们将其中的4层(即i=3)拿出来分析一下。 在插入节点之前,update[3]指向头结点,rank[3]=0,rank[0]=2,第三层左边节点到右边节点的跨度是4,那么从图中可以看出,新节点的跨度=左边节点(即插入节点的前驱)跨度-(rank[ 0]-rank[3]),这里的rank[0]-rank[3]可以进一步模型化为rank[0]-rank[i],从上文中可以看出来,实际上rank[0]-rank[i]就表示,插入节点与插入节点前驱节点之间的节点数

    14.6K108发布于 2018-10-11
  • 来自专栏烟草的香味

    数据结构之跳表

    跳表来了, 顾名思义, 跳表就是可以跳跃的表, 我简单画了张图: 在原来链表的基础上, 建立一个新的索引链表, 原链表没两个建立一个 原来查找节点5的访问顺序是: 1->2->3->4->5->6, 共遍历了6个节点 现在在索引的基础上查找5的访问顺序是: 1->3->5->5->6(先访问索引), 共遍历了5个节点 这种链表加索引的结构就是跳表 查找 从刚才的介绍中可以看出, 加了一层索引后, 访问效率变高了 原来链表访问节点128需要遍历128次, 现在只需要遍历14次就可以, 很明显的看出, 跳表确实可以提高查询效率 时间复杂度 在一个链表种, 查询时间复杂度是O(n) 那么, 添加了索引之后, 跳表的查询时间复杂度能优化多少呢 那么如何保证跳表的平衡, 避免跳表因为插入而出现复杂度退化呢? , 比如: 链表共又3级索引, 随机数是2, 那么就将新插入的节点添加到第一、二级索引中, 如下图: 以上, 就是跳表的简单介绍!!

    56530发布于 2019-07-25
  • 来自专栏yuyy.info技术专栏

    跳表:为什么Redis一定要用跳表来实现有序集合?

    每一层最多遍历3个节点(我认为遍历2个就够,k-1层的z是不用遍历的,在k+1层已经遍历过了,下面是老老师的解释),此时查找时间复杂度为O(logn),和二分查找相同。 在第k-1级索引中,y和z之间只有3个结点(包含y和z),所以,我们在K-1级索引中最多只需要遍历3个结点,依次类推,每一级索引都最多只需要遍历3个结 点。 跳表是不是很浪费内存? 总的索引结点大约就是n/3+n/9+n/27+…+9+3+1=n/2,空间占用减少一半。时间复杂度为3*log3n。 跳表索引动态更新 当我们不停地往跳表中插入数据时,如果我们不更新索引,就有可能出现某2个索引结点之间数据非常多的情况。极端情况下,跳表还会退化成单链表。 当然,Redis之所以用跳表来实现有序集合,还有其他原因。 跳表相对于红黑树来说更简单。 跳表更加灵活,它可以通过改变索引构建策略,有效平衡执行效率和内存消耗。

    1K11编辑于 2022-11-16
  • 来自专栏易困爱吃冰激凌

    Redis数据结构详解(3)-redis中的“排序好手”(跳表skiplist)

    跳表跳表,之所以叫跳表,就是因为它可以跳~(不是 是因为跳表可以通过节点的跃迁更快地找到目标值。 相比之前简单链表要通过8个指针来寻址,跳表的复杂度低了一点。不过我们还不满足,我们这次把部分元素的层数增加到3层再看一下。 根据上面的概率,我们可以得出: 节点层数恰好为1的概率为\frac{3}{4} 节点层数恰好为2的概率为\frac{1}{4}\cdot\frac{3}{4} 节点层数恰好为3的概率为\frac{1}{ 4}\cdot\frac{1}{4}\cdot\frac{3}{4} ……概率分布…… 因为一层需要一个指针,那么求一个节点的平均指针数如下: 1\cdot\frac{3}{4}+2\cdot(\frac {1}{4}\cdot\frac{3}{4})+……+n\cdot(\frac{1}{4})^{n-1}\cdot\frac{3}{4}=\frac{3}{4}\cdot\sum\_{i=1}^{+\infty

    93040编辑于 2022-04-01
  • 来自专栏计算机技术

    Skiplist跳表的通俗理解

    跳表就是跨越层级的管理,这种管理结构就存在多样性了: 总经理-部门经理-总监-组长-基层员工。 这一管理层级肯定存在。 总经理-部门经理-组长-基层员工。这一管理层级可能存在。 这种跨层管理就是跳表跳表有什么好处就是执行命令速度快,总经理可以直接给基层员工安排任务。所以跳表要解决的问题就是提高有序表的查询速度。 skip_list.print() ret = skip_list.search(3) print(3, "find", ret) 运行结果: 0层 : 2,4,6, 1层 2, 4层 : 5层 : 6层 : 7层 : 8层 : 9层 : 2 find True 4 find False 0层 : 2,3,6, 1层 : 2,3, 2层 : 2,3, 3层 : 2,3, 4 层 : 3, 5层 : 6层 : 7层 : 8层 : 9层 : 3 find True 更多内容请关注微信公众号: IT技术漫漫谈

    56090编辑于 2022-04-02
领券