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

Leetcode 1206. 设计跳表 (算法实现跳表的代码)_第1张图片

 

Leetcode 1206. 设计跳表 (算法实现跳表的代码)_第2张图片

 

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

Leetcode 1206. 设计跳表 (算法实现跳表的代码)_第3张图片

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

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

然后最难是插入操作

Leetcode 1206. 设计跳表 (算法实现跳表的代码)_第4张图片

我们需要首先记录下来,每一层第一个小于要插入元素的节点。然后从最下层开始插入,最下面一层一定要插入,依次向上以每一层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);
        }
    }

 

 

 

你可能感兴趣的:(算法)