附William Pugh的论文 Skip Lists: A Probabilistic Alternative to Balanced Trees

写在前面

以下内容针对的是Skip List的插入和删除,建议你先到其他地方大概了解一下Skip List长什么样子的,然后再过来看看这篇,最好还是看一眼论文先,部分挺容易看懂的。Redis中的Sorted Set基本就是使用Skip List,只是稍作修改。


初识 Skip List

Skip List 是一种数据结构,实质上为一个链表,专门用于存储有序元素,提供的查找速度可与平衡二叉树媲美,优点是实现简单。

论文中Skip List就是长上面这样的,每个节点有多个forward指针,指向在其后面的元素。将forward指针分层,称为level,level为1的那层就是单纯的有序单链表,随着层次递增,元素会越来越少。比如level的取值范围可以是[1, 32]


Skip List 的插入

先快速看一眼下面翻译过来的伪码实现。

void Insert(list, searchKey, newValue)
{
local update[1..MaxLevel];
x = list->header;
// 查找searchKey应存放的位置
for(i = list->level to 1)
{
while(x->forward[i]->key < searchKey)
x = x->forward[i];
// 位置关系: x->key < searchKey <= x->forward[i]->key
update[i] = x; // 看上行注释便知update保存的是什么
}
x = x->forward[1]; // 这在最低层
if(x->key == searchKey)
{
// 已有相同的key,替换即可
x->value = newValue;
}
else
{
lv = randomLevel(); // 为新节点随机取个level
if(lv > list->level) // 特殊处理:新节点level比当前最大level高
{
for(i = list->level+1 to lv)
update[i] = list->header;
list->level = lv;
}
x = createNode(v, searchKey, newValue);
for(i = 1 to lv) // 调整相关指针
{
x->forward[i] = update[i]->forward[i];
update[i]->forward[i] = x;
}
}
}

实现原理是,用一个update数组保存"最大且小于searchKey的元素",用它来调整涉及到的指针指向。搜索时从高层往低层搜索,顺便记录update数组,调整指针时从低层往高层调整。可能出现的情况是,新节点的level大于原来list的最大level,此时需要更新一下list的最大level。

randomLevel()比较容易实现,就是抛硬币法,有概率性,越高的level出现频率越低,因为不能直接一下子就返回过大的数字。返回一个数字n表示抛了n+1次才出现反面,但要求n<=MaxLevel。这种取level的方式很巧妙。


Skip List 的删除

void Delete(list, searchKey)
{
int update[1..MaxLevel];
x = list->header;
// 查找searchKey的存放位置
for(i = list->level to 1)
{
while(x->forward[i]->key < searchKey)
x = x->forward[i];
update[i] = x;
}
x = x->forward[i];
if(x->key == searchKey) // 若命中,则删
{
// 调整指向x的指针
for(i = 1 to list->level)
{
if(update[i]->forward[i] != x) break;
update[i]->forward[i] = x->forward[i]
}
free(x);
// 可能需要更新list的max level
while(list->level > 1 && !list->header->forward[list->level])
list->level = list->level - 1;
}
}

看过Insert之后,这个不用解释也能看懂了。

探索Skip List (跳跃表)的更多相关文章

  1. skip list跳跃表实现

    跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义,跳表是由William Pugh发明的,这位确实是个大牛,搞出一 ...

  2. 探索c#之跳跃表(SkipList)

    阅读目录: 基本介绍 算法思想 演化步骤 实现细节 总结 基本介绍 SkipList是William Pugh在1990年提出的,它是一种可替代平衡树的数据结构. SkipList在实现上相对比较简单 ...

  3. 跳跃表Skip List的原理和实现

    >>二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果 ...

  4. skip跳跃表的实现

    skiplist介绍 跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义, 跳表是由William Pugh发明的, ...

  5. 跳跃表Skip List【附java实现】

    skip list的原理 Java中的LinkedList是一种常见的链表结构,这种结构支持O(1)的随机插入及随机删除, 但它的查找复杂度比较糟糕,为O(n). 假如我们有一个有序链表如下,如果我们 ...

  6. 数据结构与算法(c++)——跳跃表(skip list)

    今天要介绍一个这样的数据结构: 单向链接 有序保存 支持添加.删除和检索操作 链表的元素查询接近线性时间 ——跳跃表 Skip List 一.普通链表 对于普通链接来说,越靠前的节点检索的时间花费越低 ...

  7. 讲讲跳跃表(Skip Lists)

    跳跃表(Skip Lists)是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的.在大部分情况下,跳跃表的效率可以和平衡树相媲美,并且在实现上比平衡树要更为 ...

  8. 跳跃表Skip List的原理

    1.二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果需要的是一个 ...

  9. Skip List(跳跃表)原理详解与实现【转】

    转自:http://dsqiu.iteye.com/blog/1705530 Skip List(跳跃表)原理详解与实现 本文内容框架: §1 Skip List 介绍 §2 Skip List 定义 ...

随机推荐

  1. Mybatis学习笔记(二) —— mybatis入门程序

    一.mybatis下载 mybaits的代码由github.com管理,下载地址:https://github.com/mybatis/mybatis-3/releases 下载完后的目录结构: 二. ...

  2. spring 事务 配置 多个

    Spring中事务控制相关配置: <bean id="txManager" class="org.springframework.jdbc.datasource.D ...

  3. P3225 [HNOI2012]矿场搭建

    传送门 对于一个点双联通分量,如果它连接了两个或更多割点 那么不论哪个点GG都有至少一条路通到其他的点双联通分量,所以我们不用考虑 如果它只连接一个割点,如果这个割点GG,那整个块也一起GG,所以要再 ...

  4. 页面布局常用,让子级div排排坐

    画页面的时候经常遇到页面布局的问题,父级div包裹多个子div很常见,代码如下: <div> <div style='width:100px;height: 100px;backgr ...

  5. @RequestParam详解以及加与不加的区别

    以前写controller层的时候都是默认带上 @RequestParam 的, 今天发现不加@RequestParam 也能接收到参数 下面我们来区分一下加与不加的区别 这里有两种写法 @Reque ...

  6. Trees on the level UVA - 122 (二叉树的层次遍历)

    题目链接:https://vjudge.net/problem/UVA-122 题目大意:输入一颗二叉树,你的任务是按从上到下,从左到右的顺序输出各个结点的值.每个结点都按照从根节点到它的移动序列给出 ...

  7. tencent intern learning

    gslb全局负载均衡   (负载均衡的问题就是某些session保存在某台服务器中,这个用户就只能用那台服务器服务了) jwt vs 传统cookies & session  (jwt类似于公 ...

  8. ColorCtr控制颜色渐变

    ColorCtr控制颜色渐变 public class ColorCtr : MonoBehaviour { public static global_color Instance;         ...

  9. LeetCode 704.二分查找(C++)

    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1. 示例 1: 输入: num ...

  10. 【计算机网络】一步一步学习IP路由流程

    TCP/IP协议簇是目前互联网应用最广的协议栈,谈到TCP/IP协议栈就不能不讲一讲IP路由的问题,因为在我们使用的网络通信中几乎每时每刻都在发生着IP路由的事件…….当你在网络世界中还是一位新手的时 ...