zoukankan      html  css  js  c++  java
  • 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驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    Android传递中文参数方法(之一)
    配置类与yaml
    修改ip失败,一个意外的情况处理方法
    oracle 自增序列与触发器
    Excel导入数据带小数点的问题
    数据库null与空的区别
    小米手机无法打开程序报错Unable to instantiate application com.android.tools.fd.runtime.BootstrapApplication的解决办法
    gradle类重复的问题解决方法
    windowSoftInputMode属性讲解
    android studio 的配置
  • 原文地址:https://www.cnblogs.com/itdef/p/8886957.html
Copyright © 2011-2022 走看看