leveldb skiplist的改编非并发去除内存池版本 代码练习

// 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 -1; } else if (a > b) { return +1; } else { return 0; } } }; unsigned GetRand() { static std::default_random_engine e; static std::uniform_int_distribution<unsigned> u(0, 1000); 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 = 12 }; 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) == 0); } 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 >= 0); return (next_[n]); } void SetNext(int n, Node* x) { assert(n >= 0); next_[n] = (x); } Node* NoBarrier_Next(int n) { assert(n >= 0); return next_[n]; } void NoBarrier_SetNext(int n,Node* x) { assert(n >= 0); next_[n] = (x); } private: Node* next_[1]; }; 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 - 1)]; 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(0); } 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(0); } 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 = 4; int height = 1; while (height < kMaxHeight && ((GetRand() % kBranching) == 0)) { height++; } assert(height > 0); 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) < 0); } 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() - 1; 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 == 0) { 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() - 1; while (true) { assert(x == head_ || compare_(x->key, key) < 0); Node* next = x->Next(level); if (next == NULL || compare_(next->key, key) >= 0) { if (level == 0) { 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() - 1; while (true) { Node* next = x->Next(level); if (next == NULL) { if (level == 0) { 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(0 /* any key will do */, kMaxHeight)), max_height_((1)) { for (int i = 0; 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 = 0; 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(10)); SkipList<Key, Comparator>::Iterator iter(&list); assert(!iter.Valid()); iter.SeekToFirst(); assert(!iter.Valid()); iter.Seek(100); assert(!iter.Valid()); iter.SeekToLast(); assert(!iter.Valid()); } const int N = 2000; const int R = 5000; std::set<Key> keys; Comparator cmp; SkipList<Key, Comparator> list(cmp); { for (int i = 0; i < N; i++) { Key key = GetRand() % R; if (keys.insert(key).second) { list.Insert(key); } } for (int i = 0; i < R; i++) { if (list.Contains(i)) { assert(keys.count(i)== 1); } else { assert(keys.count(i)== 0); } } } // Simple iterator tests { SkipList<Key, Comparator>::Iterator iter(&list); assert(!iter.Valid()); iter.Seek(0); 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 = 0; 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 = 0; j < 3; 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 0; }
把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
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
2017-04-19 动态规划与贪婪算法学习笔记
2016-04-19 网络高效编程 读书笔记