探索Skip List (跳跃表)
附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 (跳跃表)的更多相关文章
- skip list跳跃表实现
跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义,跳表是由William Pugh发明的,这位确实是个大牛,搞出一 ...
- 探索c#之跳跃表(SkipList)
阅读目录: 基本介绍 算法思想 演化步骤 实现细节 总结 基本介绍 SkipList是William Pugh在1990年提出的,它是一种可替代平衡树的数据结构. SkipList在实现上相对比较简单 ...
- 跳跃表Skip List的原理和实现
>>二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果 ...
- skip跳跃表的实现
skiplist介绍 跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义, 跳表是由William Pugh发明的, ...
- 跳跃表Skip List【附java实现】
skip list的原理 Java中的LinkedList是一种常见的链表结构,这种结构支持O(1)的随机插入及随机删除, 但它的查找复杂度比较糟糕,为O(n). 假如我们有一个有序链表如下,如果我们 ...
- 数据结构与算法(c++)——跳跃表(skip list)
今天要介绍一个这样的数据结构: 单向链接 有序保存 支持添加.删除和检索操作 链表的元素查询接近线性时间 ——跳跃表 Skip List 一.普通链表 对于普通链接来说,越靠前的节点检索的时间花费越低 ...
- 讲讲跳跃表(Skip Lists)
跳跃表(Skip Lists)是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的.在大部分情况下,跳跃表的效率可以和平衡树相媲美,并且在实现上比平衡树要更为 ...
- 跳跃表Skip List的原理
1.二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果需要的是一个 ...
- Skip List(跳跃表)原理详解与实现【转】
转自:http://dsqiu.iteye.com/blog/1705530 Skip List(跳跃表)原理详解与实现 本文内容框架: §1 Skip List 介绍 §2 Skip List 定义 ...
随机推荐
- C语言中typedef的解释_2
typedef工具是一个高级数据特性.利用typedef可以为某一类型自定义一个新的名称.这样可以提高程序的可读性,可移植性,向用户表明特定用途. typedef没有创建任何新的类型,它只是为某个已存 ...
- Kibana6.2.x 插件理解
官方地址:https://www.elastic.co/guide/en/kibana/current/development-uiexports.html Type Purpose hacks An ...
- C#校验手机端或客户端
以下代码用来检查,客户端是手机端还是PC端 string strUserAgent = Request.UserAgent.ToString().ToLower(); bool isMobile = ...
- [CF1051F]The Shortest Statement (LCA+最短路)(给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路)
题目:给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路 n≤100000,m≤100000,m-n≤20. 首先看到m-n≤20这条限制,我们可以想到是围绕这个20来做这道题. 即如果我们 ...
- 江西财经大学第一届程序设计竞赛 E
链接:https://www.nowcoder.com/acm/contest/115/E来源:牛客网 题目描述 当你的好友给你发来一条消息,你的消息列表上就会置顶显示该好友的名字以及该好友发给你的消 ...
- django 视图view
视图里一般是函数和类,需要返回响应. 试图分为2种:2. CBV(class base view) FBV(function base view) from django.views import V ...
- Asp.net获取系统信息
[DllImport("kernel32")] public static extern void GlobalMemoryStatus(ref MEMORY_INF ...
- Photoshop入门教程(三):图层
学习心得:图层可以说是Photoshop的核心,看似简单,但是对于图像的各种编辑都是基于图层.他就像一层透明的.没有厚度的玻璃纸,每张玻璃纸设置不同的效果,层层叠加,最后显现出绚烂的效果. 在进行图像 ...
- 结合element-ui表格自动生成sku规格列表
最近在写一个根据输入的规格,属性值动态生成sku表格,实现的效果大致如图,这是在vue项目里,结合element-UI表格写的,写好了就整理了一下,把代码贴上来,方便以后使用,不过代码里还是有一些重复 ...
- java——为什么要有接口?和抽象类有什么不一样?
1.接口不是类,为什么? 接口如果是类,那就失去了java引入接口的意义了. java之所以引入接口,就是为了弥补不能多继承的缺点,在java中每个类只能有一个超类,但却可以实现多个接口. 2.接口可 ...