-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdesign_skiplist.cpp
More file actions
130 lines (117 loc) · 3.06 KB
/
design_skiplist.cpp
File metadata and controls
130 lines (117 loc) · 3.06 KB
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
* =====================================================================================
*
* Filename: design_skiplist.cpp
*
* Description: 1206. Design Skiplist, https://leetcode.com/problems/design-skiplist
*
* Version: 1.0
* Created: 10/01/2021 14:49:05
* Revision: none
* Compiler: gcc
*
* Author: xianfeng.zhu@gmail.com
* Organization:
*
* =====================================================================================
*/
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <vector>
struct Node {
int val;
std::vector<Node*> next;
explicit Node(int num, int size) : val(num), next(size, nullptr) {}
};
// Random level
class Skiplist {
public:
Skiplist() : head_(0, kMaxLevel) { std::srand(std::time(nullptr)); }
bool search(int num) {
Node* node = &head_;
for (int i = cur_level_ - 1; i >= 0; i--) {
node = findClosest(node, i, num);
if (node->next[i] != nullptr && node->next[i]->val == num) {
return true;
}
}
return false;
}
void add(int num) {
const int level = randomLevel();
Node* node = &head_;
Node* newNode = new Node(num, level);
for (int i = cur_level_ - 1; i >= 0; i--) {
node = findClosest(node, i, num);
if (i < level) {
if (node->next[i] == nullptr) {
node->next[i] = newNode;
} else {
newNode->next[i] = node->next[i];
node->next[i] = newNode;
}
}
}
if (level > cur_level_) {
for (int i = cur_level_; i < level; i++) {
head_.next[i] = newNode;
}
cur_level_ = level;
}
}
bool erase(int num) {
std::vector<Node*> prevs(cur_level_);
Node* node = &head_;
for (int i = cur_level_ - 1; i >= 0; i--) {
node = findClosest(node, i, num);
prevs[i] = node;
}
Node* target = prevs[0]->next[0];
if (target == nullptr || target->val != num) {
// Not exists
return false;
}
// Erase target node and free memory
for (int i = 0; i < cur_level_; i++) {
if (prevs[i]->next[i] == target) {
prevs[i]->next[i] = target->next[i];
}
}
delete target;
// Update current level
while (cur_level_ > 1 && head_.next[cur_level_ - 1] == nullptr) {
cur_level_--;
}
return true;
}
private:
Node* findClosest(Node* head, int level, int val) {
Node* ptr = head;
while (ptr->next[level] != nullptr && ptr->next[level]->val < val) {
ptr = ptr->next[level];
}
return ptr;
}
int randomLevel() {
auto factor = []() -> double { return static_cast<double>(std::rand()) / RAND_MAX; };
int level = 1;
while (factor() < kRandFactor && level < kMaxLevel) {
level++;
}
return level;
}
private:
const int kMaxLevel = 32;
const double kRandFactor = 0.25f;
int cur_level_ = 1;
Node head_;
};
int main(int argc, char* argv[]) {
const int target = 3;
Skiplist sk_list;
sk_list.add(target);
const bool exist = sk_list.search(target);
printf("search %d -> %d\n", target, exist);
return 0;
}