skiplist 是组成有序集合(sort set)的重要数据结构
1. skiplist 图示介绍
a. 单链表
b. 第二层中,第一层中每两个元素,提取出一个元素。(可以跳跃个
c. 第三层中,以第二层为基础,第二层中每两个元素,提取出一个元素。(可以跳跃
d.第四层中,以第三层为基础,第三层中每两个元素,提取出一个元素。
(可以跳跃
e.最终一层层向上,每层的元素数量递减,等比数列。类似于平衡树结构。
具体元素组成的跳跃表
这样标准的跳跃链表:其不难得出时间复杂度为
但是维护这样标准的跳跃表(上一层元素的数量是当前层元素数量的
因此采用随机法来生成层级,每一个新的元素的层级都是随机出来的。
最终生成的跳跃表可能如下图所示:
每一层都可以看成是单链表,第一层包含所有的元素。
- skiplist算法
- 查找算法
查找19步骤:
a 从最高层即第三层开始
b 19比6大,向前移动
c 19比21小,向下移动
d 19比12大,向前移动
e 19比17大,向前移动
f 找到19了。
伪代码算法如下
function search(list, searchKey) {
x = list->header;
for (i = list->level; i > 0; i--) {
while (x->forward[i]->key < searchKey) {
x = x->forward[i];
}
}
x = x->forward[1];
if (x->key == searchKey) {
return x->value;
}
return 'not found';
}
- 插入算法
插入17步骤:
a 从最高层即第四层开始
b 17比6大,向前移动
c 17比25小,向下移动
d 17比9大,向前移动
e 17比25小,向下移动
f 17比12大,向前移动
g 17 比 19小,待插入
h 随机出一个层级,假设2层
i 17的第二层指针为9的前指针,9的前指针指向17
j 17的第一层指针为12的前指针,12的前指针指向17
算法伪代码
function insert(list, searchKey, newValue) {
update[1, ...., maxLevel];
x = list->header;
for (i = list->level; i > 0; i--) {
while (x->forward[i]->key < searchKey) {
x = x->forward[i];
}
update[i] = x;
}
x = x->forward[1];
if (x->key == searchKey && x->value == newValue) {
return 'exists';
}
level = randomLevel();
x = makeNode(level, searchKey, value);
for (i = 1; i < level; i++) {
x->forward[i] = update[i]->forward[i];
update[i]->forward[i] = x;
}
}
- 删除算法
插入的逆算法,先查找,在删除,释放节点
算法伪代码如下
function delete(list, searchKey) {
update[1, ...., maxLevel];
x = list->header;
for (i = list->level; i > 0; i--) {
while (x->forward[i]->key < searchKey) {
x = x->forward[i];
}
update[i] = x;
}
x = x->forward[1];
if (x->key != searchKey) {
return 'not found';
}
for (i = 1; i < list->level; i++) {
if (update[i]->forward[i] == x) {
update[i]->forward[i] = x->forward[i];
free(x);
}
}
}
- random算法
算法伪代码
function randomLevel() {
level = 1;
while (random() < p && level < maxLevel) {
level ++;
}
return level;
}