Leetcode 1206. 设计跳表 (算法实现跳表的代码)

 

 

这道题目是Redis,LevelDB中使用到的经典数据结构。通过这道题目可以理解跳表的插入,删除,查找过程。这里提供的代码是标准的算法实现版本,通过使用常规链表指针和一个向下的指针来实现。该实现比较直观简单,便于理解。

跳表的直观理解图示,最底层是完整链表,上层在底层链表的基础上,随机将一些节点向上复制,连接起来, 节点的结构如下:

class Node {
public:
    Node *right;
    Node *down;
    int val;
    Node(Node *right, Node *down, int val): right(right), down(down), val(val) {}
};

查找过程,从上到下查找,每次如果能向左,就向左走,如果不能向左,那么就向下。
 

    bool search(int target) {
        auto p = head;
        while(p != nullptr){
            while(p->right != nullptr && p->right->val < target){
                p = p->right;
            }
            if(p->right != nullptr && p->right->val == target){
                return true;
            }
            p = p->down;
        }
        return false;
    }

删除操作和查找操作类似,因为我们在查找的时候,总是通过前一个节点来找右边的满足要求的节点,所以删除也一样,每一层都要删除。

    bool erase(int num) {
        auto p = head;
        bool found = false;
        while(p != nullptr){
            while(p->right != nullptr && p->right->val < num){
                p = p->right;
            }
            if(p->right != nullptr && p->right->val == num){
                found = true;
                p->right = p->right->right;
            }
            p = p->down;
        }
        return found;
    }

然后最难是插入操作

我们需要首先记录下来,每一层第一个小于要插入元素的节点。然后从最下层开始插入,最下面一层一定要插入,依次向上以每一层0.5^(i)的概率插入。

我们要注意,如果最上面多出了一层,那么此时要创建一个新的头节点

    void add(int num) {
        auto p = head;
        pathList.clear();
        while(p != nullptr){
            while(p->right != nullptr && p->right->val < num){
                p = p->right;
            }
            pathList.push_back(p);
            p = p->down;
        }
        bool isInsert = true;
        Node *down = nullptr;
        while(isInsert && !pathList.empty()){
            auto node = pathList.back();
            pathList.pop_back();
            node->right = new Node(node->right, down, num);
            down = node->right;
            isInsert = (rand() & 1) == 0; // %50概率向上插入
        }
        if(isInsert){
            head = new Node(new Node(NULL, down, num), head, -1);
        }
    }

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值