跳表

跳表的简单实现,支持插入,删除和查询


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
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <random>
#include <vector>
#include <optional>

template <class Key, class Value, class Compare = std::less<Key>>
class SkipList {
private:
Compare compare = Compare();

struct Node {
Node *right;
Node *down;
Key key;
Value value;
Node(Node *right, Node *down)
: right(right), down(down) {}
Node(Node *right, Node *down, Key key, Value value)
: right(right), down(down), key(key), value(value) {}
};
Node *head;
const static int MAX_LEVEL = 32;
std::vector<Node *> pathList;

public:
SkipList() {
head = new Node(nullptr, nullptr);
pathList.reserve(MAX_LEVEL);
}
~SkipList() {
Node *p = head, *ptr = nullptr, *tmp = nullptr;
while (p) {
ptr = p->right;
tmp = nullptr;
while (ptr) {
tmp = ptr->right;
delete ptr;
ptr = tmp;
}
tmp = p->down;
delete p;
p = tmp;
}
}

bool Find(const Key &x) { // 查找 x 是否存在
Node *p = head;
while (p) {
// 向右寻找区间
while (p->right && compare(p->right->key, x)) {
p = p->right;
}
// 没有目标值则向下走
if (p->right == nullptr || compare(x, p->right->key)) {
p = p->down;
}
// 找到目标值
else {
return true;
}
}
return false;
}

std::optional<Value> GetValue(const Key &x) { // 查找 x 对应 value
if (!Find(x)) {
return std::nullopt;
}
Node *p = head;
while (p) {
// 向右寻找区间
while (p->right && compare(p->right->key, x)) {
p = p->right;
}
// 没有目标值则向下走
if (p->right == nullptr || compare(x, p->right->key)) {
p = p->down;
}
// 找到目标值
else {
return std::make_optional<Value>(p->right->value);
}
}
return std::nullopt;
}

bool Insert(const Key &x, const Value &y) { // 添加 x, y
if (Find(x)) {
return false;
}
// 记录前驱路径
pathList.clear();
Node *p = head;
while (p) {
// 依次向右找到次小于 x 的 p
while (p->right && compare(p->right->key, x)) {
p = p->right;
}
pathList.push_back(p);
p = p->down;
}

bool insertUp = true;
Node *downNode = nullptr;
// downNode 为下一层对应相同权值的点
while (insertUp && pathList.size() > 0) {
Node *insert = pathList.back();
pathList.pop_back();
// 加入新节点
insert->right = new Node(insert->right, downNode, x, y);
// 新节点设为 downNode
downNode = insert->right;
// 50% 概率向上加节点
insertUp = (rand() % 2 == 0);
}
// 插入新的首节点
if (insertUp) head = new Node(new Node(nullptr, downNode, x, y), head);
return true;
}

bool Erase(const Key &x) {
// 删除 x
Node *p = head;
bool seen = false;
while (p) {
// 向右找到次小于 x 的点
while (p->right && compare(p->right->key, x)) p = p->right;
// 没有找到,往下一层
if (p->right == nullptr || compare(x, p->right->key)) {
p = p->down;
} else {
// 查找到,删除节点,结果记为 true
// 继续往下搜索,删除下层的节点
seen = true;
Node *ptr = p->right;
p->right = p->right->right;
delete ptr;
p = p->down;
}
}
// 返回是否成功删除
return seen;
}
};