跳跃表(英文名: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. git配置github链接

    1.百度git官网-下载最新版git 2.一路默认下一步安装 3.打开 git bash here 命令行 4.注册github账号(用自己的邮箱就可以,不会英文可以用谷歌翻译)注册成功后建立项目 5 ...

  2. 记录---Testin上新手测试用例设计实战---碎乐3.2.0

    平台上给的版本是碎乐3.12版的,但是平台上给的安装包下载不了,所以加群咨询之后给出了直接去手机应用商店下载搜索到的版本的对策.所以就那应用商店中找到的3.2.0版本来设计测试用例.因为任务中没有给出 ...

  3. C++0x,std::move和std::forward解析

    1.std::move 1.1std::move是如何定义的 template<typename _Tp> constexpr typename std::remove_reference ...

  4. CSP201612-1:中间数

    引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...

  5. POJ 3415 Common Substrings(后缀数组)

    Description A substring of a string T is defined as: T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|. Given t ...

  6. HTML5文档的各个组成部分分类

    <!DOCTYPE html><!--声明文档结构类型--> <html lang="zh-cn"><!--声明文档文字区域--> ...

  7. Thunder团队第一周 - Scrum会议7

    Scrum会议7 小组名称:Thunder 项目名称:爱阅app Scrum Master:宋雨 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康 ...

  8. 一个例子说明mouseover事件与mouseenter事件的区别

    <html> <head> <meta charset="UTF-8"> <title>haha</title> < ...

  9. PokeCats开发者日志(十一)

      现在是PokeCats游戏开发的第六十天的上午,易版权的状态变为了待收证,但愿不久就能送到了吧.

  10. C# Parsing 类实现的 PDF 文件分析器

    下载示例 下载源代码 1. 介绍 这个项目让你可以去读取并解析一个PDF文件,并将其内部结构展示出来. PDF文件的格式标准文档可以从Adobe那儿获取到. 这个项目基于“PDF指南,第六版,Adob ...