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;
}
View Code

把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

作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
阿里打赏 微信打赏
原文地址:https://www.cnblogs.com/itdef/p/8886957.html