跳跃表 https://61mon.com/index.php/archives/222/
跳跃表(英文名:Skip List),于 1990 年 William Pugh 发明,是一个可以在有序元素中实现快速查询的数据结构,其插入,查找,删除操作的平均效率都为
。
跳跃表的整体性能可以和二叉查找树(AVL 树,红黑树等)相媲美,其在 Redis 和 LevelDB 中都有广泛的应用。

每个结点除了数据域,还有若干个指针指向下一个结点。
整体上看,Skip List 就是带有层级结构的链表(结点都是排好序的),最下面一层(level 0)是所有结点组成的一个链表,依次往上,每一层也都是一个链表。不同的是,它们只包含一部分结点,并且越往上结点越少。仔细观察你会发现,通过增加层数,从当前结点可以直接访问更远的结点(这也就是 Skip List 的精髓所在),就像跳过去一样,所以取名叫 Skip List(跳跃表)。
具体参考:https://61mon.com/index.php/archives/222/
/**
*
* author 刘毅(Limer)
* date 2017-09-01
* mode C++
*/
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std; #define P 0.25
#define MAX_LEVEL 32 struct Node
{
int key;
Node ** forward;
Node(int key = , int level = MAX_LEVEL)
{
this->key = key;
forward = new Node*[level];
memset(forward, , level * sizeof(Node*));
}
}; class SkipList
{
private:
Node * header;
int level;
private:
int random_level();
public:
SkipList();
~SkipList();
bool insert(int key);
bool find(int key);
bool erase(int key);
void print();
}; int SkipList::random_level()
{
int level = ; while ((rand() & 0xffff) < (P * 0xffff) && level < MAX_LEVEL)
level++; return level;
} SkipList::SkipList()
{
header = new Node;
level = ;
} SkipList::~SkipList()
{
Node * cur = header;
Node * next = nullptr; while (cur)
{
next = cur->forward[];
delete cur;
cur = next;
} header = nullptr;
} bool SkipList::insert(int key)
{
Node * node = header;
Node * update[MAX_LEVEL];
memset(update, , MAX_LEVEL * sizeof(Node*)); for (int i = level - ; i >= ; i--)
{
while (node->forward[i] && node->forward[i]->key < key)
node = node->forward[i];
update[i] = node;
} node = node->forward[]; if (node == nullptr || node->key != key)
{
int new_level = random_level(); if (new_level > level)
{
for (int i = level; i < new_level; i++)
update[i] = header; level = new_level;
} Node * new_node = new Node(key, new_level); for (int i = ; i < new_level; i++)
{
new_node->forward[i] = update[i]->forward[i];
update[i]->forward[i] = new_node;
} return true;
} return false;
} bool SkipList::find(int key)
{
Node * node = header; for (int i = level - ; i >= ; i--)
{
while (node->forward[i] && node->forward[i]->key <= key)
node = node->forward[i]; if (node->key == key)
return true;
} return false;
} bool SkipList::erase(int key)
{
Node * node = header;
Node * update[MAX_LEVEL];
fill(update, update + MAX_LEVEL, nullptr); for (int i = level - ; i >= ; i--)
{
while (node->forward[i] && node->forward[i]->key < key)
node = node->forward[i];
update[i] = node;
} node = node->forward[]; if (node && node->key == key)
{
for (int i = ; i < level; i++)
if (update[i]->forward[i] == node)
update[i]->forward[i] = node->forward[i]; delete node; for (int i = level - ; i >= ; i--)
{
if (header->forward[i] == nullptr)
level--;
else
break;
}
} return false;
} void SkipList::print()
{
Node * node = nullptr; for (int i = ; i < level; i++)
{
node = header->forward[i];
cout << "Level " << i << " : ";
while (node)
{
cout << node->key << " ";
node = node->forward[i];
}
cout << endl;
} cout << endl;
} int main()
{
SkipList sl; // test "insert"
sl.insert();
sl.insert();
sl.insert(); sl.insert();
sl.insert();
sl.insert(); sl.insert();
sl.insert();
sl.insert();
sl.insert();
sl.insert();
sl.insert();
sl.insert();
sl.insert();
sl.print(); // test "find"
cout << sl.find() << endl;
cout << sl.find() << endl;
cout << sl.find() << endl << endl; // test "erase"
sl.erase();
sl.print();
sl.erase();
sl.print();
sl.erase();
sl.print(); return ;
}
跳跃表 https://61mon.com/index.php/archives/222/的更多相关文章
- skip跳跃表的实现
skiplist介绍 跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义, 跳表是由William Pugh发明的, ...
- skip list跳跃表实现
跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义,跳表是由William Pugh发明的,这位确实是个大牛,搞出一 ...
- 基于跳跃表的 ConcurrentSkipListMap 内部实现(Java 8)
我们知道 HashMap 是一种键值对形式的数据存储容器,但是它有一个缺点是,元素内部无序.由于它内部根据键的 hash 值取模表容量来得到元素的存储位置,所以整体上说 HashMap 是无序的一种容 ...
- [Redis]Redis的设计与实现-链表/字典/跳跃表
redis的设计与实现:1.假如有一个用户关系模块,要实现一个共同关注功能,计算出两个用户关注了哪些相同的用户,本质上是计算两个用户关注集合的交集,如果使用关系数据库,需要对两个数据表执行join操作 ...
- redis跳跃表
最近在阅读redis设计与实现,关于redis数据结构zset的一种底层实现跳跃表一直没有太理解,所以在搜了一下资料,终于搞懂了它的设计思路,记录一下. 参考链接:https://mp.weixin. ...
- redis的跳跃表
跳跃表是一种插入.查询.删除的平均时间复杂度为O(nlogn)的数据结构,在最差情况下是O(n),当然这几乎很难出现. 和红黑树相比较 最差时间复杂度要差很多,红黑树是O(nlogn),而跳跃表是O( ...
- Redis 的底层数据结构(跳跃表)
字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...
- Redis学习之zskiplist跳跃表源码分析
跳跃表的定义 跳跃表是一种有序数据结构,它通过在每个结点中维持多个指向其他结点的指针,从而达到快速访问其他结点的目的 跳跃表的结构 关于跳跃表的学习请参考:https://www.jianshu.co ...
- lucene反向索引——倒排表无论是文档号及词频,还是位置信息,都是以跳跃表的结构存在的
转自:http://www.cnblogs.com/forfuture1978/archive/2010/02/02/1661436.html 4.2. 反向信息 反向信息是索引文件的核心,也即反向索 ...
随机推荐
- 使用python+selenium控制手工已打开的浏览器
我们可以利用Chrome DevTools协议.它允许客户检查和调试Chrome浏览器. 打开cmd,在命令行中输入命令: chrome.exe --remote-debugging-port=922 ...
- jmeter获取cookies
使用场景:登录后,后续的请求操作需获取到JSESSIONID才可进行 1.将jmeter的bin目录下的jmeter.properties文件中的CookieManager.save.cookies= ...
- TPO-12 C1 Revise a Hemingway paper
TPO-12 C1 Revise a Hemingway paper 第 1 段 1.Listen to a conversation between a student and a professo ...
- .NET中发送邮件的实现
.NET中发送邮件 注意: 1.引用下列命名空间: using System.Net; using System.Net.Mail; 2.确保你使用的发送邮件的邮箱开启了stamp服务等. /// & ...
- 【springmvc+mybatis项目实战】杰信商贸-5.生产厂家DAO+SERVICE+CONTROLLER+JSP+配置文件
上一篇我们创建了工程和一个Factory的po对象(javaBean),我们也写好了Mapper的映射文件,接下来我们来完成生产厂家的DAO与SERVICE,以及CONTROLLER,还有做显示的JS ...
- 从零开始的Python学习Episode 4——列表
一.列表 列表与数组相似,定义一个列表 a=[1,2,3,4,5] 1.基本操作 a=[1,2,3,4] #切片 范围取值时,包括第一项但不包括最后一项,顾头不顾尾 print(a[0:]) #从头到 ...
- java poi技术读取到数据库
https://www.cnblogs.com/hongten/p/java_poi_excel.html java的poi技术读取Excel数据到MySQL 这篇blog是介绍java中的poi技术 ...
- 【转载】图解Java常用数据结构(一)
图解Java常用数据结构(一) 作者:大道方圆 原文:https://www.cnblogs.com/xdecode/p/9321848.html 最近在整理数据结构方面的知识, 系统化看了下Jav ...
- MySQL Proxy使用
使用MySQL将读写请求转接到主从Server. 一 安装MySQL Proxy MySQL Proxy的二进制版非常方便,下载解压缩后即用. 解压缩的目录为: $mysql-proxy_instal ...
- 衡量生活成本:消费者价格指数(CPI, Consumer Price Index)
经济学家应该如何把经济中的许多价格加总成一个单一指数,从而能够衡量价格的总体水平呢?他们可以简单地计算所有产品与服务价格的平均值,但是这种方法的不足之处是把所有的产品与服务等同处理.由于人们购买的鸡比 ...