SkipList
概述
跳表是个概率性数据结构,可以被看作是二叉树的一个变种。跳表是由William Pugh在1990年发明的。它是一种用户维护有序元素的数据结构。
特征
一个跳表,应该具有以下特征:
- 一个跳表应该有几个层(level)组成;
- 跳表的第一层包含所有的元素;
- 每一层都是一个有序的链表;
- 如果元素x出现在第i层,则所有比i小的层都包含x;
- 第i层的元素通过一个down指针指向下一层拥有相同值的元素;
- 在每一层中,-1和1两个元素都出现(分别表示INT_MIN和INT_MAX);
- Top指针指向最高层的第一个元素。
构造过程
跳表的构造过程是:
- 给定一个有序的链表。
- 选择连表中最大和最小的元素,然后从其他元素中按照一定算法随即选出一些元素,将这些元素组成有序链表。这个新的链表称为一层,原链表称为其下一层。
- 为刚选出的每个元素添加一个指针域,这个指针指向下一层中值同自己相等的元素。Top指针指向该层首元素
- 重复2、3步,直到不再能选择出除最大最小元素以外的元素。
复杂度
- The expected number of levels is O( log n )
(here n is the numer of elements) - The expected time for insert/delete/find is O( log n )
- The expected size (number of cells) is O(n )
复杂度证明
关于时空效率的证明:
空间复杂度 O(n)
对于每层的期待:第一层n,第二层n/2,第三层n/22,…,直到 n/2log n=1。所以,总空间需求:
S = n + n/2 + n/22 + … + n/2log n < n(1 + 1/2 + 1/22 + … + 1/2∞) =2n
因此他的空间复杂度为 2n = O(n)
Skip List高度
对每层来说,它会向上增长的概率为1/2,则第m层向上增长的概率为1/2m;n个元素,则在m层元素数目的期待为Em = n/2m;当Em = 1,m = log2n即为层数的期待。故其高度期待为 Eh = O(log n)。
*关于“高概率(high probability)”的定义:
对于事件A,如果它发生的概率至少为1-cα/nα,其中cα仅取决于α,那么我们称它为高概率。
在牺牲时间和/或空间的情况下,我们可以选择α的值。
- 查找的复杂度:
claim:在高概率的前提下,查找的时间复杂度为O(log n) -
插入的复杂度:
claim:在高概率的前提下,插入的时间复杂度为O(log n)
首先通过查找找到要插入的位置:O(log n)
之后进行插入,同时对每层进行对应的更新(依照概率决定是否向上增长):o(log n) - 删除的复杂度:
claim:在高概率的前提下,删除的时间复杂度为O(log n)
实现源码
参考资料
http://www.kernelchina.org/algorithm/SL.ppt
http://epaperpress.com/sortsearch/skl.html
http://www.spongeliu.com/63.html
http://www.cnblogs.com/flyfy1/archive/2011/02/24/1963347.html
http://courses.csail.mit.edu/6.046/spring04/handouts/skiplists.pdf