跳跃表(英文名:Skip List),于 1990 年 William Pugh 发明,是一个可以在有序元素中实现快速查询的数据结构,其插入,查找,删除操作的平均效率都为

跳跃表的整体性能可以和二叉查找树(AVL 树,红黑树等)相媲美,其在 RedisLevelDB 中都有广泛的应用。

每个结点除了数据域,还有若干个指针指向下一个结点。

整体上看,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/的更多相关文章

  1. skip跳跃表的实现

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

  2. skip list跳跃表实现

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

  3. 基于跳跃表的 ConcurrentSkipListMap 内部实现(Java 8)

    我们知道 HashMap 是一种键值对形式的数据存储容器,但是它有一个缺点是,元素内部无序.由于它内部根据键的 hash 值取模表容量来得到元素的存储位置,所以整体上说 HashMap 是无序的一种容 ...

  4. [Redis]Redis的设计与实现-链表/字典/跳跃表

    redis的设计与实现:1.假如有一个用户关系模块,要实现一个共同关注功能,计算出两个用户关注了哪些相同的用户,本质上是计算两个用户关注集合的交集,如果使用关系数据库,需要对两个数据表执行join操作 ...

  5. redis跳跃表

    最近在阅读redis设计与实现,关于redis数据结构zset的一种底层实现跳跃表一直没有太理解,所以在搜了一下资料,终于搞懂了它的设计思路,记录一下. 参考链接:https://mp.weixin. ...

  6. redis的跳跃表

    跳跃表是一种插入.查询.删除的平均时间复杂度为O(nlogn)的数据结构,在最差情况下是O(n),当然这几乎很难出现. 和红黑树相比较 最差时间复杂度要差很多,红黑树是O(nlogn),而跳跃表是O( ...

  7. Redis 的底层数据结构(跳跃表)

    字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...

  8. Redis学习之zskiplist跳跃表源码分析

    跳跃表的定义 跳跃表是一种有序数据结构,它通过在每个结点中维持多个指向其他结点的指针,从而达到快速访问其他结点的目的 跳跃表的结构 关于跳跃表的学习请参考:https://www.jianshu.co ...

  9. lucene反向索引——倒排表无论是文档号及词频,还是位置信息,都是以跳跃表的结构存在的

    转自:http://www.cnblogs.com/forfuture1978/archive/2010/02/02/1661436.html 4.2. 反向信息 反向信息是索引文件的核心,也即反向索 ...

随机推荐

  1. Kotlin对象:仅一行代码就可创建安全的单例

    作者:Antonio Leiva 时间:Jun 20, 2017 原文链接:https://antonioleiva.com/objects-kotlin/ Kotlin对象是Android开发人员不 ...

  2. 【JAVA】关于java中 类.class.getResource("/").getPath()获取路径有空格的问题

    写了一个web工程,在本地测试正确,但是部署到服务器上就出现错误.原因是读取不到配置文件. 后来从打印出来的文件路径中发现是用Java的class.getResource("/") ...

  3. Java开发工程师(Web方向) - 04.Spring框架 - 第3章.AOP技术

    第3章--AOP技术 Spring框架 - AOP概述 笔记https://my.oschina.net/hava/blog/758873Spring框架 - AOP使用 笔记https://my.o ...

  4. leetcode-回文链表

    请判断一个链表是否为回文链表. 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶:你能否用 O(n) 时间复杂 ...

  5. Y460蓝牙键盘无法连接问题解决

    mac坏了,无法启动,一直没时间去修理. 近期把大学的时候用的笔记本又翻了出来,小Y,经典的“娱乐本” Y460. Y460上之前被自己各种重装系统,反复从windows到双系统,再到linux之间来 ...

  6. Python练习——循环2

    1.求1~100之间能被7整除,但不能同时被5整除的所有整数 . for i in range(1,101): if i%7 == 0 and i%5 !=0: print(i) 2.输出“水仙花数” ...

  7. 常用web资源

    ip相关 新浪:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip=220.181.38.110 (不带参数本机) ...

  8. 用URL传参带特殊字符,特殊字符丢失

    文章:URL中编码URL特殊字符 文章:用URL传参带特殊字符,特殊字符丢失(encode) 如果url中有特殊字符,需要对url进行编码,否则特殊字符丢失,导致最终接收到的值不对.

  9. java定时执行任务(一)

    需求: 经常遇到这样的需求:要求每天执行一次任务,执行任务时间是凌晨3点 实现: 为了便于检测,我假设的是下一分钟执行任务,每10秒重复执行.(对应现实项目:每天3点执行任务.那么就是下一个3点执行任 ...

  10. ZooKeeper server &&client

    写了一个关于zookeepeer应用的简单demo 服务端定时的向zookeeper集群注册,客户端监听zookeeper服务节点变化,一旦变化,立刻响应,更新服务端列表 服务端代码: #includ ...