今天学习了跳跃表,记录一下下~
一、跳跃表简介
跳跃表是一种随机化数据结构,基于并联的链表,其效率可以比拟平衡二叉树,查找、删除、插入等操作都可以在对数期望时间内完成,对比平衡树,跳跃表的实现要简单直观很多。
以下是一个跳跃表的例图(来自维基百科):
从图中可以看出跳跃表主要有以下几个部分构成:
1、 表头head:负责维护跳跃表的节点指针
2、 节点node:实际保存元素值,每个节点有一层或多层
3、 层level:保存着指向该层下一个节点的指针
4、 表尾tail:全部由null组成
跳跃表的遍历总是从高层开始,然后随着元素值范围的缩小,慢慢降低到低层。
用大白话来解释一下跳跃表:
如上图,
跳跃表在redis中主要是有序表的一种底层实现。对于普通链表的查找,即使有序,我们也不能使用二分法,需要从头开始,一个一个找,时间复杂度为O(n)。而对于跳跃表,从名字可以看出跳跃表的优势就在于可以跳跃。如何做到呢?在于其特殊的层设计。比如我们查找46,普通链表只能从头开始查找,比对-3,2,17...直到46,要比对7次。但是对于跳跃表,我们可以从最高层开始查找:
第一步:在L4层直接与55比对,发现大了,退回到第3层
第二步:在L3层与21比对,发现小了,继续往前比对55,发现大了,退回到第二层
第三步:在L2层与37比对,发现小了,往前,与55比对,发现大了,退回到第一层
第四步:在第1层,与46比对,查找成功。
共比对了6次,比普通链表只节省了一次,似乎没什么优势。但如果细想,当链表比较长的时候,在高层查找时,跳过的元素数量将相当可观,提速的效果将非常明显。比如如果元素在55之后,在L4层,我们直接就跳过了7个元素,这是非常大的进步。
跳跃表(Skiplist)是一种随机化数据结构,它在查找、插入、删除等操作的期望时间复杂度都能达到对数级,并且编码相对简单许多,跳跃表目前是Redis中用于存储有序集合的底层数据结构,另外可以存储有序集的数据结构是字典,Redis中还有一种底层数据结构intset可以用来存储有序整数集。
Redis作者通过对原有的跳跃表进行修改,包括span的设计、score值可以重复、添加tail与backward指针等,从而实现了排序功能,从尾至头反向遍历的功能等。