概述
SkipList 是由William Pugh发明的一种数据结构,它的作用类似平衡二叉树,对查找,删除,插入操作的时间复杂度为O(logN),是一种十分高效的查找结构。SkipList使用随机化的平衡方案取代了平衡二叉树的严格的平衡方案,因此它也是一种随机化的数据结构。SkipList基于并联的链表,是对有序的链表附加上随机个数的前进的链接,使得在查找过程中可以快速地跳过部分链表而得名。
如上图所示,a为普通的排好序的LinkList,在a中查找一个元素,最坏情况下,我们需要对比所有的节点,如果修改成如b那样,间隔的list中的元素加上指向前面第二个的元素指针,则查找一个元素最多需要【n/2】+ 1次对比,同理对应c来说,则需要【n/4】 + 1次,如果对任意第2^i个节点拥有i个指针来指向前面的i个节点,那么其查找效率就会降到logN,但是这种数据结构虽然可以很快的进行查找,但是对于插入和删除操作确实不切实际的。一个拥有k个向前指针的节点称为k层节点,像之前描述的结构,节点的层次分布模式为:%50为1层,25%为2层,12.5%为三层,以此类推。如果按一定比例来随机分配节点的层次的话(如图中的e),节点的第i个向前指针只需指向第i层的下一个节点。当插入一个节点时,随机的选择它的层次,并且不再需要改变。虽然有时候某些层次的安排会带来低效的执行效率,但是因为是随机化的,所以这种情况是很罕见的。
初始化
SkipList的所有层级的子list都终结于NIL(不带任何合法值的元素),刚创建的SkipList的层级为1,只有一个头结点,并且只包含一个指向NIL的向前结点。
随机化层次选择
设拥有第i个向前指针的节点,同时拥有第i+1个向前指针分布比例为p,若有一半的节点有第i个向前指针的节点,同时拥有第i+1个向前指针,则p等于1/2.则随机化的层次选择过程如下:
randomLevel() lvl := 1 -- random() that returns a random value in [0...1) while random() < p and lvl < MaxLevel do lvl := lvl + 1 return lvl
这里有个MaxLevel,它的值为 MaxLevel =L(N)= log(1/p)N (p=1/2)=log(2).N,它表示跳跃表最大允许的层次。
效率分析
设C(K)为查找第k个节点需要消耗的时间,则:
C(0) = 0
C(k) = (1–p) (在同一层查找) + p (向下一层查找)
化简得
C(k) = (1–p) (1 + C(k)) + p (1 + C(k–1))
C(k) = 1/p + C(k–1)
C(k) = k/p
因为k《=MaxLevel=L(n)/p + 1/(1–p),为O(logN)
查找过程
Search(list, searchKey) x := list.eader -- loop invariant: x.key < searchKey for i := list.level downto 1 do while x.forward[i].key < searchKey do x := x.forward[i] -- x.key < searchKey <= x.forward[1].key x := x.forward[1] if x.key = searchKey then return x.value else return failure
模拟查找过程:
查找6的过程如下:
- 首先从最高层开始,发现6在 header跟6节点之间
-
然后继续降到第三层
- 还是发现6在 header跟6节点之间,降到第二层
- 第一层时,发现6在节点3和6直接,此时x指向3这个节点
-
3的下一个节点是6,刚好找到
插入过程
Insert(list, searchKey, newValue)
local update[1..MaxLevel]
x := list.header
for i := list.level downto 1 do
while x.forward[i].key < searchKey do
x := x.forward[i]
-- x.key < searchKey £ x.forward[i].key
update[i] := x
x := x.forward[1]
if x.key = searchKey then x.value := newValue
else
lvl := randomLevel()
if lvl > list.level then
for i := list.level + 1 to lvl do
update[i] := list.header
list.level := lvl
x := makeNode(lvl, searchKey, value)
for i := 1 to level do
x.forward[i] := update[i].forward[i]
update[i].forward[i] := x
删除过程
Delete(list, searchKey) local update[1..MaxLevel] x := list.header for i := list.level downto 1 do while x.forward[i].key < searchKey do x := x.forward[i] update[i] := x x := x.forward[1] if x.key = searchKey then for i := 1 to list.level do if update[i].forward[i] != x then break update[i].forward[i] := x.forward[i] free(x) while list.level > 1 and list.header.forward[list.level] = NIL do list.level := list.level – 1
SCALA实现
package chiyx.algo.datastruct
/**
* Created with IntelliJ IDEA.
* scala版本的跳跃表的实现
* @author qianshang@taobao.com
* @since 下午11:00 13-9-2
*
*/
class SkipList[T <% Ordered[T]] {
/**
* 随机化的概率,每层节点拥有上一层指针的概率
*/
private val P = 0.5
/**
* 最高层级为8,则 N的合适范围在 2^^8
*/
private val MaxLevel = 8
private val header: SkipNode[T] = new SkipNode[T](MaxLevel)
/**
* 当前的最大层级编号,从0开始编号
*/
private var level = 0
/**
* 随机产生插入节点的层高
* @return
*/
def randomLevel = {
val lvl = (Math.log(1.0 - Math.random()) / Math.log(1 - P)).toInt
Math.min(lvl, MaxLevel)
}
/**
* 检查是否包含元素
* @param o
* @return
*/
def contains(o: T) = {
var x = header
for (i <- level.to(0, -1)) {
while (x.forward(i) != null && x.forward(i).value < o) {
x = x.forward(i)
}
}
x = x.forward(0)
x != null && x.value.equals(o)
}
/**
* 插入元素
* @param o
*/
def insert(o: T) {
var x = header
val update = new Array[SkipNode[T]](MaxLevel + 1)
for (i <- level.to(0, -1)) {
while (x.forward(i) != null && x.forward(i).value < o) {
x = x.forward(i)
}
update(i) = x
}
x = x.forward(0)
/**
* 如果不存在,则创建节点
*/
if (x == null || x.value != o) {
val lvl = randomLevel
if (lvl > level) {
for (i <- level to lvl) {
update(i) = header
}
level = lvl
}
x = new SkipNode[T](o, lvl)
for (i <- 0 to lvl) {
x.forward(i) = update(i).forward(i)
update(i).forward(i) = x
}
}
}
/**
* 删除操作
* @param o
*/
def delete(o: T) {
var x = header
val update = new Array[SkipNode[T]](MaxLevel + 1)
for (i <- level.to(0, -1)) {
while (x.forward(i) != null && x.forward(i).value < o) {
x = x.forward(i)
}
update(i) = x
}
x = x.forward(0)
//元素存在的情况下才需要删除
if (x != null && x.value == o) {
for (i <- 0 to level) {
if (update(i).forward(i) == x) {
update(i).forward(i) = x.forward(i)
}
}
while (level > 0 && header.forward(level) == null) {
level = level - 1
}
}
}
}
/**
* 跳跃表中的节点
* @tparam T
*/
private class SkipNode[T](val level: Int) {
var value: T = _
/**
* 指向多个层级的下个节点的指针数组
*/
val forward: Array[SkipNode[T]] = new Array[SkipNode[T]](level + 1)
def this(ve: T, level: Int) = {
this(level)
value = ve
}
}
object SkipListApp {
def main(args: Array[String]) {
val sList = new SkipList[Int]
sList insert 5
sList insert 4
sList insert 6
sList insert 9
println( sList contains 6)
sList delete 6
println( sList contains 6)
}
}