1.SkipList是什么?
SkipList其实是针对链表查找效率低的特点的一种改进,结合链表和二分查找,查询时间复杂度为O(logn)的一种数据结构
特点:
1)链表中结点是有序的
2)能够满足类似二分查找的“跳跃式”查找
2.SkipList如何实现类“二分查找”?(图片引用自https://time.geekbang.org/column/article/42896)
先来看一般情况,通常我们是通过遍历的方式来查找链表中的元素,但是如果链表是有序的,那么是否可以实现二分查找?答案是肯定的。
如果增加一层“索引”,如下所示
举个例子,如果查找16这个元素,在链表中需要查找10次,而在这里则1->4->7->9->13->13->16,一共7次
那么,如果再加多一层“索引”呢?
这时查找就变成1->7->13>13->16。显然,“索引”越多,查找效率越高。虽然在这个例子中提高的效率并不是特别明显,但是在数据量大的时候这种方式还是能够大大提高效率的
3.SkipList的插入和删除和索引更新
1)插入其实就是先查找后插入的一个过程
2)删除需要删除原始链表中的结点以及索引中的对应结点
3)索引动态更新策略
如果往SkipList中不断插入,却不更新索引的话,查找效率就会逐渐降低,最坏情况下甚至退化到O(n)
假设SkipList一共有N层索引,我们一般是使用一个随机函数,生成一个1~N之间的随机数K,在1~K层索引中为刚插入的结点创建索引
4.redis中的sorted set
zset由一个dict和skiplist组成,数据结构如下
字典的作用:可以在O(1)时间复杂度内通过对象查找到分值,如zscore命令
跳表的作用:避免每次按分值区间查找(zrange)或者rank(zrank)的时候都要进行排序
值得一提的是,虽然zset使用了dict和skiplist来保存有序集合元素,但这两种数据结构都会通过指针来指向共享的相同元素的成员和分值。