数据结构之跳跃表

我们知道,线性表一般有两种结构,数组和链表,数组一般在物理上是连续的内存块,而链表则不是。数组在使用前就需要分配好内存空间而链表不需要,数组中根据下标就能定位到一个元素,复杂度为O(1) ,而链表一般查找一个元素复杂度为O(N)。
数组插入、删除则需要移动元素,而链表则不需要。

从上面可以看到,链表对于频繁的插入、删除支持比数组好,但是查找效率低,为此有人基于链表提出了跳跃表的概念。其思想就是给链表加上索引。

在这里插入图片描述

大概的意思就是上面这样,上面L1,L2都是索引层,每层会指向下一层,最终会指向原始链表。

如果我们通过单链表查找8的话,需要8次,但是加上两层索引后,我们通过索引能够加快查询,这时候查询逻辑为:
在L2层判断8,1比10小,比1大,当前查找节点设置为1,然后在L1层查找,8比10小,比7大,当前节点设置为7,在下一层查找,找到8。

跳表中理想情况下,每层的个数是下一层的 1/2 ,比较关键的是在索引层怎么确定元素是否参与索引,而跳跃表的处理则很随机,一般通过一个随机函数

实际使用时,如果高度太高,会造成空间浪费,我们要做一个空间和时间的平衡。那么跳跃表的高度多少最合适?
假设跳跃表中的元素个数为N,当跳跃表的高度为log(N)时,跳跃表进化为一个二叉树结构,其查询次数与二分查找法一致。这无疑最理想的结果。

如果有一亿条记录,高度log(N)约等于30。redis中,最大高度也就是32,最多可以存几亿条记录。通常,我们用不了这么多记录。所以高度可以降低一点。
跳跃表性质如下:

  • 由很多层结构组成,层高level是通过一定的概率随机产生的。
  • 每一层都是一个有序的链表,默认是升序
  • 最底层(Level 1)的链表包含所有元素。
  • 如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现。
  • 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

跳跃表元素插入哪层一般使用随机算法,可以理解为抛硬币

在java中提供了跳跃表的实现: ConcurrentSkipListMap

redis中在两个地方用到了跳跃表,一个是实现有序集合键(zset),另一个是在集群节点中用作内部数据结构,相比红黑树而言,跳跃表有一下优势:

  • 对于插入而言,跳跃表只需要前后指针即可,而红黑树则需要旋转。
  • 对于区间查找来说,跳跃表比红黑树简单快速
  • 跳跃表比红黑树更容易实现
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值