
// 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-windowsdbskiplist.h
leveldb-windowsdbskiplist_test.cc