数据结构之跳跃表

数据结构之跳跃表,第1张

数据结构之跳跃

我们知道,线性表一般有两种结构,数组和链表,数组一般在物理上是连续的内存块,而链表则不是。数组在使用前就需要分配好内存空间而链表不需要,数组中根据下标就能定位到一个元素,复杂度为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),另一个是在集群节点中用作内部数据结构,相比红黑树而言,跳跃表有一下优势:

对于插入而言,跳跃表只需要前后指针即可,而红黑树则需要旋转。对于区间查找来说,跳跃表比红黑树简单快速跳跃表比红黑树更容易实现

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5707304.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存