跳表是一个很有意思的数据结构,它实现简单,但是性能又可以和平衡二叉搜索树差不多。

据MIT公开课上教授的讲解,它的想法和纽约地铁有异曲同工之妙,简而言之就是不断地增加“快线”,从而降低时间复杂度。

当“快线”的数量为lgn时,我们就得到了现在的快表——一个类似于平衡二叉搜索树的数据结构。

网上没有比较标准的实现方案,CLRS中也没有给出伪代码。(可能是因为他们觉得太容易实现了...)所以我给出是一个完全由我自己根据快表性质写的一个版本,如果大家有更好的实现版本欢迎和我分享。

增加层数的方案用的是抛硬币,即根据随机数来确定是否增加“快线”,这也是MIT公开课上给出的一个比较简单的实现方法。

代码如下:(仅供参考)

 class Skiplist {
private :
struct Node {
int key;
Node * prev;
Node * next;
Node * down;
Node * top;
Node() : key(), prev(nullptr), next(nullptr), down(nullptr), top(nullptr) {}
};
private :
Node * head;
int level;
int size;
private :
void bindNewNode(Node * x, Node * p);
void delNode(Node * x);
Node * searchNode(int key);
public :
Skiplist() : head(new Node), level(),size()
{head->key = INT_MIN; srand(static_cast<int>(time()));}
~Skiplist() {delete head;}
void insert(int key);
void remove(int key);
bool search(int key) {return (searchNode(key) != nullptr);}
void showSkiplist();
int getLevel() {return level;}
int getSize() {return size;}
}; void Skiplist::bindNewNode(Node * x, Node * p) {
if (!x->next) {
x->next = p;
p->prev = x;
}
else {
p->next = x->next;
x->next->prev = p;
p->prev = x;
x->next = p;
}
} void Skiplist::insert(int key) {
Node * p = new Node;
p->key = key; Node * x = head;
while () { //find the prev node of p, which represents the right insert place
if (x->key <= key) {
if (x->next)
x = x->next;
else if (x->down)
x = x->down;
else break;
}
else if (x->prev->down)
x = x->prev->down;
else {
x = x->prev;
break;
}
}
bindNewNode(x, p);
while (rand() % ) { //throw the coin, then judge whether it needs to be higher according to the results
Node * highp = new Node;
highp->key = key;
while (!x->top && x->prev)
x = x->prev;
if (x->top) {
x = x->top;
bindNewNode(x, highp);
highp->down = p;
p->top = highp;
}
else { //already the top, add a sentry
Node * top = new Node;
x = top;
top->key = INT_MIN;
top->down = head;
head->top = top;
head = top;
bindNewNode(top, highp);
highp->down = p;
p->top = highp;
++level;
}
p = highp;
}
++size;
} void Skiplist::delNode(Node * x) {
if (!x->next) { //node x is the last one
if (x->prev == head && head->down) { //x is not at the bottom and x is the last one of this level
head = head->down;
head->top = nullptr;
delete x->prev;
--level;
}
else
x->prev->next = nullptr;
}
else {
x->prev->next = x->next;
x->next->prev = x->prev;
}
delete x;
} void Skiplist::remove(int key) {
Node * x = searchNode(key);
if (x) {
while (x->down) {
Node * y = x->down;
delNode(x);
x = y;
}
delNode(x);
--size;
}
} Skiplist::Node * Skiplist::searchNode(int key) {
Node * x = head;
while () { //find the prev node of p, which represents the right insert place
if (x->key == key)
return x;
else if (x->key < key) {
if (x->next)
x = x->next;
else if (x->down)
x = x->down;
else
return nullptr;
}
else if (x->prev->down)
x = x->prev->down;
else {
return nullptr;
}
}
} void Skiplist::showSkiplist() {
Node * x = head, * y = head;
while (y) {
x = y;
while (x) {
if (x->prev != nullptr)
cout << x->key << ' ';
x = x->next;
}
cout << endl;
y = y->down;
}
}

skip-list(跳表)原理及C++代码实现的更多相关文章

  1. 聊聊Mysql索引和redis跳表 ---redis的有序集合zset数据结构底层采用了跳表原理 时间复杂度O(logn)(阿里)

    redis使用跳表不用B+数的原因是:redis是内存数据库,而B+树纯粹是为了mysql这种IO数据库准备的.B+树的每个节点的数量都是一个mysql分区页的大小(阿里面试) 还有个几个姊妹篇:介绍 ...

  2. JAVA SkipList 跳表 的原理和使用例子

    跳跃表是一种随机化数据结构,基于并联的链表,其效率可比拟于二叉查找树(对于大多数操作需要O(log n)平均时间),并且对并发算法友好. 关于跳跃表的具体介绍可以参考MIT的公开课:跳跃表 跳跃表的应 ...

  3. skip list跳跃表实现

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

  4. 自己动手实现java数据结构(九) 跳表

    1. 跳表介绍 在之前关于数据结构的博客中已经介绍过两种最基础的数据结构:基于连续内存空间的向量(线性表)和基于链式节点结构的链表. 有序的向量可以通过二分查找以logn对数复杂度完成随机查找,但由于 ...

  5. levelDB跳表实现

    跳表的原理就是利用随机性建立索引,加速搜索,并且简化代码实现难度.具体的跳表原理不再赘述,主要是看了levelDB有一些实现细节的东西,凸显自己写的实现不足之处. 去除冗余的key template& ...

  6. 3.3.7 跳表 SkipList

    一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下,ConcurrentHashMap 存取速度是ConcurrentSki ...

  7. C语言跳表(skiplist)实现

    一.简介 跳表(skiplist)是一个非常优秀的数据结构,实现简单,插入.删除.查找的复杂度均为O(logN).LevelDB的核心数据结构是用跳表实现的,redis的sorted set数据结构也 ...

  8. redis为何单线程 效率还这么高 为何使用跳表不使用B+树做索引(阿里)

    如果想了解 redis 与Memcache的区别参考:Redis和Memcache的区别总结 阿里的面试官问问我为何redis 使用跳表做索引,却不是用B+树做索引 因为B+树的原理是 叶子节点存储数 ...

  9. skiplist(跳表)的原理及JAVA实现

    前记 最近在看Redis,之间就尝试用sortedSet用在实现排行榜的项目,那么sortedSet底层是什么结构呢? "Redis sorted set的内部使用HashMap和跳跃表(S ...

随机推荐

  1. MarkDown简易教程+语法

    一.标题 一个#是一级,两个#是二级,最大六级 二.字体 1.加粗 要加粗的文字左右分别用两个*号包起来 2.斜体 要倾斜的文字左右分别用一个*号包起来 3.斜体加粗 要倾斜和加粗的文字左右分别用三个 ...

  2. [ACTF2020 新生赛]Include

    0x00 知识点 本地文件包含 ?file=php://filter/read/convert.base64-encode/resource=index.php ?file=php://filter/ ...

  3. VBE2019的下载、安装和使用(最新版2020.2.22)

    VBE2019可用于XP系统.Windows 7和Windows 10的32位.64位Office对应的VBA环境 安装包下载地址:VBE2019-Setup.zip 下载后解压缩,直接双击安装(请勿 ...

  4. zabbix安装及配置

    一.安装zabbix_server 二.安装zabbix_agent 三.zabbix配置详解

  5. 2019年Unity3D游戏开发前景预测及总结

    由于现在随着互联网时代的到来,人们上网玩游戏的越来越多,导致游戏开发人才供不应求,如果你想成为一名优秀的开发者,那么掌握Unity3D开发技术是不可跳过的一环.随着移动互联网的发展,移动端游戏日益盛行 ...

  6. rocketmq 使用

    rocketmq  基本使用可以看官网和官网给的demo. https://github.com/apache/rocketmq/tree/master/example 这里主要说明几个点:rocke ...

  7. PAT Advanced 1004 Counting Leaves (30) [BFS,DFS,树的层序遍历]

    题目 A family hierarchy is usually presented by a pedigree tree. Your job is to count those family mem ...

  8. ACwing算法基础课听课笔记(第一章,基础算法一)(二分)

    二分法: 在看这个视频前,我对于二分法是一头雾水的,又加上这个算法平常从来没写过所以打了一年了还没正式搞过.视频提到ACwing上的一道题,我用自以为聪明的方法去做,结果TLE了,实在丢人,不说了,开 ...

  9. JAVA 算法练习(一)

    用java写了几道编程题目,分享给大家 语法和C语言几乎一样,不懂 java 会 c 也可以看明白的. 最大连续数列和 题目说明 对于一个有正有负的整数数组,请找出总和最大的连续数列.给定一个int数 ...

  10. linux 解压命令总结

    常用Linux 命令: [转自]https://www.jianshu.com/p/ca41f32420d6 解压缩 .tar 解包:tar xvf FileName.tar 打包:tar cvf F ...