跳跃表(英文名: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. Linux命令应用大词典-第44章 PPPoE配置

    44.1 pppoe-setup:配置PPPoE客户端 44.2 ppoe-connect:管理PPPoE链路 44.3 pppoe-start:启动PPPoE链路 44.4 pppoe-stop:关 ...

  2. 第六模块:WEB框架开发 第1章·Django框架开发1~50

    01-Django基础介绍 02-Web应用程序1 03-Web应用程序2 04-http请求协议1 05-http请求协议2 06-http协议之响应协议 07-wsgire模块1 08-wsgir ...

  3. 用Python实现一个端口扫描,只需简单几步就好

    一.常见端口扫描的原理 0.秘密扫描 秘密扫描是一种不被审计工具所检测的扫描技术. 它通常用于在通过普通的防火墙或路由器的筛选(filtering)时隐藏自己. 秘密扫描能躲避IDS.防火墙.包过滤器 ...

  4. lintcode 二叉树后序遍历

    /** * Definition of TreeNode: * class TreeNode { * public: * int val; * TreeNode *left, *right; * Tr ...

  5. Java进阶知识点:不可变对象与并发

    一.String的不可变特性 熟悉Java的朋友都知道,Java中的String有一个很特别的特性,就是你会发现无论你调用String的什么方法,均无法修改this对象的状态.当确实需要修改Strin ...

  6. 火狐metamask账号

    火狐metamask lock trophy pyramid sunny aim inmate body sense sing castle cinnamon cram

  7. Redis+Keepalived高可用方案详细分析

    背景 目前,Redis集群的官方方案还处在开发测试中,未集成到稳定版中.且目前官方开发中的Redis Cluster提供的功能尚不完善(可参考官方网站或http://www.redisdoc.com/ ...

  8. 上层应用与wpa_supplicant,wpa_supplicant与kernel 相关socket创建交互分析

    单独拿出来,分析以下上层应用与wpa_supplicant   wpa_supplicant与kernel 的socket交互. 关联上层应用与wpa_supplicant的socket的创建.连接流 ...

  9. Python中的slice操作

    Python中slice操作的完整语法: # i默认是0 # j默认是len(S) # k的步长,默认为+1 S[i:j:k] 其中i,j,k都可以是负数: 若i < 0或者k<0,等价于 ...

  10. Ubuntu 配置 ftp freemind adb

    . 1. 配置apt-get源 配置过程 : sudo vim /etc/profile 命令, 在后面添加下面的内容; 刷新配置文件 : source /etc/profie 命令; 刷新源 : s ...