// MuSkipList.cpp: 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <random>
#include <iostream>
#include <set>
#include <assert.h> using namespace std; typedef unsigned _int64 Key; struct Comparator {
int operator()(const Key& a, const Key& b) const {
if (a < b) {
return -;
}
else if (a > b) {
return +;
}
else {
return ;
}
}
}; unsigned GetRand()
{
static std::default_random_engine e;
static std::uniform_int_distribution<unsigned> u(, );
return u(e);
}
//=================================================================== template<typename Key, class Comparator>
class SkipList {
private:
struct Node;
public:
explicit SkipList(Comparator cmp);
void Insert(const Key& key);
bool Contains(const Key& key) const; class Iterator {
public:
explicit Iterator(const SkipList* list);
bool Valid() const;
const Key& key() const;
void Next();
void Prev();
void Seek(const Key& target);
void SeekToFirst();
void SeekToLast();
private:
const SkipList* list_;
Node* node_;
};
private:
enum { kMaxHeight = };
Comparator const compare_;
Node* head_;
int max_height_;
inline int GetMaxHeight() const {
return max_height_;
}
//Random rnd_; Node* NewNode(const Key& key, int height);
int RandomHeight();
bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == ); }
bool KeyIsAfterNode(const Key& key, Node* n) const;
Node* FindGreaterOrEqual(const Key& key, Node** prev)const;
Node* FindLessThan(const Key& key) const;
SkipList(const SkipList&);
Node* FindLast() const;
void operator=(const SkipList&);
}; template<typename Key, class Comparator>
struct SkipList<Key, Comparator>::Node {
explicit Node(const Key& k) : key(k) { }
Key const key;
Node* Next(int n) {
assert(n >= );
return (next_[n]);
}
void SetNext(int n, Node* x) {
assert(n >= );
next_[n] = (x);
}
Node* NoBarrier_Next(int n) {
assert(n >= );
return next_[n];
}
void NoBarrier_SetNext(int n,Node* x) {
assert(n >= );
next_[n] = (x);
} private:
Node* next_[];
}; template<typename Key, class Comparator>
typename SkipList<Key, Comparator>::Node*
SkipList<Key, Comparator>::NewNode(const Key& key, int height) {
char* mem = new char[sizeof(Node) + sizeof(Node*) * (height - )];
return ::new (mem) Node(key);
} template<typename Key, class Comparator>
inline SkipList<Key, Comparator>::Iterator::Iterator(const SkipList* list) {
list_ = list;
node_ = NULL;
} template<typename Key, class Comparator>
inline bool SkipList<Key, Comparator>::Iterator::Valid() const {
return node_ != NULL;
} template<typename Key, class Comparator>
inline const Key& SkipList<Key, Comparator>::Iterator::key() const {
assert(Valid());
return node_->key;
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::Next() {
assert(Valid());
node_ = node_->Next();
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::Prev() {
// Instead of using explicit "prev" links, we just search for the
// last node that falls before key.
assert(Valid());
node_ = list_->FindLessThan(node_->key);
if (node_ == list_->head_) {
node_ = NULL;
}
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::Seek(const Key& target) {
node_ = list_->FindGreaterOrEqual(target, NULL);
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::SeekToFirst() {
node_ = list_->head_->Next();
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::SeekToLast() {
node_ = list_->FindLast();
if (node_ == list_->head_) {
node_ = NULL;
}
} template<typename Key, class Comparator>
int SkipList<Key, Comparator>::RandomHeight() {
// Increase height with probability 1 in kBranching
static const unsigned int kBranching = ;
int height = ;
while (height < kMaxHeight && ((GetRand() % kBranching) == )) {
height++;
}
assert(height > );
assert(height <= kMaxHeight);
return height;
} template<typename Key, class Comparator>
bool SkipList<Key, Comparator>::KeyIsAfterNode(const Key& key, Node* n) const {
// NULL n is considered infinite
return (n != NULL) && (compare_(n->key, key) < );
} template<typename Key, class Comparator>
typename SkipList<Key, Comparator>::Node* SkipList<Key, Comparator>::FindGreaterOrEqual(const Key& key, Node** prev )const
{
Node* x = head_;
int level = GetMaxHeight() - ;
while (true) {
Node* next = x->Next(level);
if (KeyIsAfterNode(key, next)) {
// Keep searching in this list
x = next;
}
else {
if (prev != NULL) prev[level] = x;
if (level == ) {
return next;
}
else {
// Switch to next list
level--;
}
}
}
} template<typename Key, class Comparator>
typename SkipList<Key, Comparator>::Node*
SkipList<Key, Comparator>::FindLessThan(const Key& key) const {
Node* x = head_;
int level = GetMaxHeight() - ;
while (true) {
assert(x == head_ || compare_(x->key, key) < );
Node* next = x->Next(level);
if (next == NULL || compare_(next->key, key) >= ) {
if (level == ) {
return x;
}
else {
// Switch to next list
level--;
}
}
else {
x = next;
}
}
} template<typename Key, class Comparator>
typename SkipList<Key, Comparator>::Node* SkipList<Key, Comparator>::FindLast()
const {
Node* x = head_;
int level = GetMaxHeight() - ;
while (true) {
Node* next = x->Next(level);
if (next == NULL) {
if (level == ) {
return x;
}
else {
// Switch to next list
level--;
}
}
else {
x = next;
}
}
} template<typename Key, class Comparator>
SkipList<Key, Comparator>::SkipList(Comparator cmp)
: compare_(cmp),
head_(NewNode( /* any key will do */, kMaxHeight)),
max_height_(())
{
for (int i = ; i < kMaxHeight; i++) {
head_->SetNext(i, NULL);
}
} template<typename Key, class Comparator>
void SkipList<Key, Comparator>::Insert(const Key& key) {
Node* prev[kMaxHeight];
Node* x = FindGreaterOrEqual(key, prev); assert(x == NULL || !Equal(key, x->key)); int height = RandomHeight();
if (height > GetMaxHeight()) {
for (int i = GetMaxHeight(); i < height; i++) {
prev[i] = head_;
} max_height_=(height);
} x = NewNode(key, height);
for (int i = ; i < height; i++) {
x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i));
prev[i]->SetNext(i, x);
}
} template<typename Key, class Comparator>
bool SkipList<Key, Comparator>::Contains(const Key& key) const {
Node* x = FindGreaterOrEqual(key, NULL);
if (x != NULL && Equal(key, x->key)) {
return true;
}
else {
return false;
}
} //=======================================================================
int main()
{
{
Comparator cmp;
SkipList<Key, Comparator> list(cmp); assert(false ==list.Contains());
SkipList<Key, Comparator>::Iterator iter(&list); assert(!iter.Valid());
iter.SeekToFirst();
assert(!iter.Valid());
iter.Seek();
assert(!iter.Valid());
iter.SeekToLast();
assert(!iter.Valid());
} const int N = ;
const int R = ;
std::set<Key> keys;
Comparator cmp;
SkipList<Key, Comparator> list(cmp);
{ for (int i = ; i < N; i++) {
Key key = GetRand() % R;
if (keys.insert(key).second) {
list.Insert(key);
}
} for (int i = ; i < R; i++) {
if (list.Contains(i)) {
assert(keys.count(i)== );
}
else {
assert(keys.count(i)== );
}
} } // Simple iterator tests
{
SkipList<Key, Comparator>::Iterator iter(&list);
assert(!iter.Valid()); iter.Seek();
assert(iter.Valid());
assert(*(keys.begin()) == iter.key()); iter.SeekToFirst();
assert(iter.Valid());
assert(*(keys.begin()) == iter.key()); iter.SeekToLast();
assert(iter.Valid());
assert(*(keys.rbegin())== iter.key());
} // Forward iteration test
for (int i = ; i < R; i++) {
SkipList<Key, Comparator>::Iterator iter(&list);
iter.Seek(i); // Compare against model iterator
std::set<Key>::iterator model_iter = keys.lower_bound(i);
for (int j = ; j < ; j++) {
if (model_iter == keys.end()) {
assert(!iter.Valid());
break;
}
else {
assert(iter.Valid());
assert(*model_iter == iter.key());
++model_iter;
iter.Next();
}
}
} // Backward iteration test
{
SkipList<Key, Comparator>::Iterator iter(&list);
iter.SeekToLast(); // Compare against model iterator
for (std::set<Key>::reverse_iterator model_iter = keys.rbegin();
model_iter != keys.rend();
++model_iter) {
assert(iter.Valid());
assert(*model_iter == iter.key());
iter.Prev();
}
assert(!iter.Valid());
} return ;
}

把LEVELDB的skiplist跳表给扣出来了 去除了内存池代码

贪图方便  还是选择了原始指针.

需要在析构函数中遍历节点 进行Node的指针的 delete

如果想使用智能指针替代 动态分配Node的指针的时候 可以考虑使用 std::array<std::shared_ptr<Node>> 或者 std::vector<std::shared_ptr<Node>>

在leveldb项目中 原代码文件路径为

leveldb-windows\db\skiplist.h

leveldb-windows\db\skiplist_test.cc

leveldb skiplist的改编非并发去除内存池版本 代码练习的更多相关文章

  1. C++实现简单的内存池

    多进程编程多用在并发服务器的编写上,当收到一个请求时,服务器新建一个进程处理请求,同时继续监听.为了提高响应速度,服务器采用进程池的方法,在初始化阶段创建一个进程池,池中有许多预创建的进程,当请求到达 ...

  2. Linux设备驱动程序 之 内存池

    内核中有些地方的内存分配是不允许失败的,为了确保这种情况下的成功分配,内核开发者建立了一种称为内存池的抽象:内存池其实就是某种形式的后备高速缓存,它试图始终保存空闲的内存,以便在紧急状态下使用: me ...

  3. linux内存池

    在内核中有不少地方内存分配不允许失败. 作为一个在这些情况下确保分配的方式, 内核 开发者创建了一个已知为内存池(或者是 "mempool" )的抽象. 一个内存池真实地只是一 类 ...

  4. Linux 内核内存池

    内核中经常进行内存的分配和释放.为了便于数据的频繁分配和回收,通常建立一个空闲链表——内存池.当不使用的已分配的内存时,将其放入内存池中,而不是直接释放掉. Linux内核提供了slab层来管理内存的 ...

  5. LevelDB学习笔记 (3): 长文解析memtable、跳表和内存池Arena

    LevelDB学习笔记 (3): 长文解析memtable.跳表和内存池Arena 1. MemTable的基本信息 我们前面说过leveldb的所有数据都会先写入memtable中,在leveldb ...

  6. Golang面向并发的内存模型

    Import Advanced Go Programming 1.5 面向并发的内存模型 在早期,CPU都是以单核的形式顺序执行机器指令.Go语言的祖先C语言正是这种顺序编程语言的代表.顺序编程语言中 ...

  7. NSOperation的start与main,并发与非并发。

    http://blog.csdn.net/a2331046/article/details/52294006 在ios4以前,只有非并发的情况下,队列会为operation开启一个线程来执行.如果是并 ...

  8. LevelDB源码分析之:arena内存管理

    一.原理 arena是LevelDB内部实现的内存池. 我们知道,对于一个高性能的服务器端程序来说,内存的使用非常重要.C++提供了new/delete来管理内存的申请和释放,但是对于小对象来说,直接 ...

  9. NSOperation的并发与非并发

    NSoperation也是多线程的一种,NSopertaion有2种形式  (1) 并发执行       并发执行你需要重载如下4个方法     //执行任务主函数,线程运行的入口函数    - (v ...

随机推荐

  1. SVN Commit:将本地代码更新到服务器代码

    1.点击客户端“TortoiseSVN” 选中后显示: 点击Import: 点击“ok”:

  2. 如何搭建python+selenium2+eclipse的环境

    搭建python和selenium2的环境(windows) 1.下载并安装python(我用的是2.7的版本) 可以去python官网下载安装:http://www.python.org/getit ...

  3. dbcp第一次获取连接的时间问题

    最近优化代码,发现第一次调用数据库连接时非常慢,往后便不再发生.经了解,数据库连接是用dbcp管理的,想在网上查找答案,但没有找到.在某人的提醒下决定研究源代码: 部分源代码如下(BasicDataS ...

  4. pta l2-10(排座位)

    题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805066135879680 题意:给宴席排座位,有n个人,m个 ...

  5. layer数据表格换行

    在使用layer数据表格的时候,默认是不可以换行的.这样显示 改动后 数据格式为   aa<br>bb就会显示为换行 比如我们的字符串是    a<br>b 这样的字符串浏览器 ...

  6. 2018年全国多校算法寒假训练营练习比赛(第四场)F:Call to your teacher

    传送门:https://www.nowcoder.net/acm/contest/76/F 题目描述 从实验室出来后,你忽然发现你居然把自己的电脑落在了实验室里,但是实验室的老师已经把大门锁上了.更糟 ...

  7. springMVC项目部署 服务器启动spring容器报错bean未从类加载器中找到

    bean未从类加载器中找到 警告: Exception encountered during context initialization - cancelling refresh attempt: ...

  8. UNITY3D 2D物流流体插件下载|Liquid Physics 2D

    制作类似<鳄鱼小顽皮爱洗澡>游戏的必备插件 下载地址: https://item.taobao.com/item.htm?spm=0.7095261.0.0.47411debZFbEUn& ...

  9. 批处理(.bat脚本)基本命令语法

    .bat脚本基本命令语法   目录批处理的常见命令(未列举的命令还比较多,请查阅帮助信息)     1.REM 和 ::     2.ECHO 和 @     3.PAUSE     4.ERRORL ...

  10. 模拟点击事件在alert前不起作用

    本来想在ajax提交前点击一下模态框,直到返回处理之前都显示正在保存,发现如标题的现象,几经折腾没找到解决办法,发现可能是 alert线程阻塞(冒泡)引起的,也没找到解决办法,于是借助第三方插件lay ...