// 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. Displacement Mapping

    [Displacement Mapping] Displacement Mapping(移位贴图). Normal maps的另一个应用是displacement mapping,在这个应用中,细节的 ...

  2. Node KeyNote

    [Node KeyNote] 1.实际上,.node文件在windows下它是一个.dll文件,在*nix下则是一个.so文件. 2.默认变量 function(exports, require, m ...

  3. SSL、TLS中间人攻击

    生成私钥 生成一个ca.key私钥签名 然后用私钥生成一个伪造证书服务器的根证书 生成一个伪造证书服务器的根证书ca.crt 在攻击主机启动路由转发功能 或者echo 1 > /proc/sys ...

  4. 字符串相似度算法(编辑距离Levenshtein Distance)的应用场景

    应用场景 DNA分析: 将DNA的一级序列如β-球蛋白基因的第一个外显子(Exon)转化为分子“结构图”,然后由所得“结构图”提取图的不变量,如分子连接性指数.以图的不变量作为自变量,再由相似度计算公 ...

  5. 无法加载DLL"***.dll":找不到指定的模块

    加载dll的路径不对. 绝对路径不合适,可以换成相对路径. 比如: 把dll放入bin目录下的debug或者release下,然后就可以直接“test.dll”了.不用加路径了. 注意:路径必须与发布 ...

  6. centos 7 下 Ceph 配置安装

    一.环境介绍 系统: CentOS Linux release 7.3.1611 (Core) 硬盘: 系统盘:300GB*2-raid 1 OSD:600GB*4-raid 5      ceph ...

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

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

  8. CSS3实现10种Loading效果(转)

    CSS3实现10种Loading效果  原文地址:http://www.cnblogs.com/jr1993/p/4622039.html 昨晚用CSS3实现了几种常见的Loading效果,虽然很简单 ...

  9. C语言之栈区、堆区

    一 局部变量存放在栈区中,函数调用结束后释放内存空间. #include "stdio.h"; #include "stdlib.h"; int *getNum ...

  10. Visual Studio 2015 自动生成 的大文件xxx.vc.db的删除问题

    用vs2015创建Visual C++项目,编写生成后,每次都会生成一个project_name.VC.db文件,而且会随着你工程修改运行变的越来越大. project_name.VC.db是sqli ...