跳表简单实现

跳表

class Skiplist {
    static const int SKIPLIST_P_VAL = RAND_MAX / 2, MAX_LEVEL = 16; // RAND_MAX是rand()所能达到的最大值。
public:
    struct Node{
        int val;
        vector<Node *> next;
        Node(int val, int size = MAX_LEVEL): val(val), next(size){}
    };
    Node head;
    int maxlevel = 1; // 记录当前最高的level

    Skiplist():head(INT_MIN, MAX_LEVEL) {
    }
    bool search(int target) {
        // 在_search后就看第一层的pre的后面一个节点val是否等于target
        auto prevs = _search(target);
        return prevs[0]->next[0] && prevs[0]->next[0]->val == target;
    }

    vector<Node *> _search(int key){
        // 此函数是跳表的核心,实现的功能是,寻找key所经历的路径。返回路径上的前置节点
        Node * cur = &head;
        vector<Node *> prevs(MAX_LEVEL);
        for(int i = maxlevel - 1; i >= 0; i--){
            // 从最顶层开始
            while(cur->next[i] && cur->next[i]->val < key){
                // 一直寻找到刚好大于key的节点的前置节点
                cur = cur->next[i];
            }
            prevs[i] = cur;
        }
        return prevs;
    }
    
    void add(int num) {
        auto prevs = _search(num); // 在当前的跳表中, num在各级跳表中的前置节点
        int level = random_level(); // level的索引是从1开始的

        // 更新maxlevel, prevs
        if(level > maxlevel){
            // 更新超出maxlevel的prevs,前置节点都为head
            for(int i = maxlevel; i < level; i++){
                prevs[i] = &head;  
            }
            maxlevel = level;
        }

        // 创建当前节点
        Node * cur = new Node(num, level);

        // 插入在prevs节点后, 从pre->nxd到pre->cur->nx
        for(int i = level - 1; i >= 0; i--){
            cur->next[i] = prevs[i]->next[i];
            prevs[i]->next[i] = cur;
        }

    }
    
    bool erase(int num) {
        auto prevs = _search(num);

        // 如果num不存在跳表中
        if(!prevs[0]->next[0] || prevs[0]->next[0]->val != num){
            return false;
        }

        Node * del = prevs[0]->next[0];
        // 删除prevs后的节点
        for(int i = 0; i < maxlevel; i++){
            if(prevs[i]->next[i] == del){
                prevs[i]->next[i] = del->next[i];
            }
        }
        delete del;

        // 更新maxlevel
        while(maxlevel > 1 && !head.next[maxlevel - 1]){
            maxlevel--;
        }
        return true;

    }
    

    static int random_level(){
        int level = 1;
        while(rand() < SKIPLIST_P_VAL && level < MAX_LEVEL){
            level++;
        }
        return level; // 此处返回的level的索引是从1开始的
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值