数据结构之跳跃表
Posted Leo Han
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之跳跃表相关的知识,希望对你有一定的参考价值。
我们知道,线性表一般有两种结构,数组和链表,数组一般在物理上是连续的内存块,而链表则不是。数组在使用前就需要分配好内存空间而链表不需要,数组中根据下标就能定位到一个元素,复杂度为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),另一个是在集群节点中用作内部数据结构,相比红黑树而言,跳跃表有一下优势:
- 对于插入而言,跳跃表只需要前后指针即可,而红黑树则需要旋转。
- 对于区间查找来说,跳跃表比红黑树简单快速
- 跳跃表比红黑树更容易实现
以上是关于数据结构之跳跃表的主要内容,如果未能解决你的问题,请参考以下文章