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-windows\db\skiplist.h

 leveldb-windows\db\skiplist_test.cc

posted on   itdef  阅读(303)  评论(0编辑  收藏  举报

编辑推荐:
· 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 网络高效编程 读书笔记

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示