-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimple_skiplsit.cpp
189 lines (164 loc) · 5.1 KB
/
simple_skiplsit.cpp
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#pragma once
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <vector>
/**
* @brief 节点类,表示跳表中的一个节点
*
* @note 该跳表主要为了解跳表的工作原理,没有使用模板定义排序器和存储的值类型,只是实现了简单的int存储和升序排序
* 生产环境中可直接使用concurrent-skiplist
*/
class Node {
public:
int value; ///< 节点的值
std::vector<Node*> forward; ///< 指向不同层级的下一个节点的指针数组
/**
* @brief 构造函数
* @param level 节点的层级
* @param value 节点的值
*/
Node(int level, int value) : value(value), forward(level + 1, nullptr) {}
};
/**
* @brief 跳表类
*/
class SkipList {
private:
int maxLevel; ///< 跳表的最大层级
float probability; ///< 节点提升层级的概率
int currentLevel; ///< 当前跳表的最高层级
Node* header; ///< 跳表的头节点
/**
* @brief 生成一个随机层级
* @return 随机生成的层级
*/
int randomLevel() {
int level = 0;
while (static_cast<float>(rand()) / RAND_MAX < probability && level < maxLevel) {
level++;
}
return level;
}
/**
* @brief 查找大于或等于指定值的节点
* @param value 指定的值
* @param update 存储每一层中最后一个小于指定值的节点
*/
void findGreaterOrEqual(int value, std::vector<Node*>& update) {
Node* current = header;
for (int i = currentLevel; i >= 0; i--) {
while (current->forward[i] && current->forward[i]->value < value) {
current = current->forward[i];
}
update[i] = current;
}
}
public:
/**
* @brief 构造函数
* @param maxLevel 跳表的最大层级
* @param probability 节点提升层级的概率
*/
SkipList(int maxLevel, float probability) : maxLevel(maxLevel), probability(probability), currentLevel(0) {
header = new Node(maxLevel, -1);
srand(static_cast<unsigned>(time(nullptr)));
}
/**
* @brief 析构函数
*/
~SkipList() {
Node* current = header;
while (current) {
Node* next = current->forward[0];
delete current;
current = next;
}
}
/**
* @brief 插入一个值到跳表中
* @param value 要插入的值
*/
void insert(int value) {
std::vector<Node*> update(maxLevel + 1, header);
findGreaterOrEqual(value, update);
Node* current = update[0]->forward[0];
if (!current || current->value != value) {
int newLevel = randomLevel();
currentLevel = std::max(currentLevel, newLevel);
Node* newNode = new Node(newLevel, value);
for (int i = 0; i <= newLevel; i++) {
newNode->forward[i] = update[i]->forward[i];
update[i]->forward[i] = newNode;
}
}
}
/**
* @brief 搜索跳表中是否存在指定值
* @param value 要搜索的值
* @return 如果存在返回true,否则返回false
*/
bool search(int value) {
std::vector<Node*> update(maxLevel + 1);
findGreaterOrEqual(value, update);
Node* current = update[0]->forward[0];
return current && current->value == value;
}
/**
* @brief 从跳表中删除指定值
* @param value 要删除的值
*/
void remove(int value) {
std::vector<Node*> update(maxLevel + 1);
findGreaterOrEqual(value, update);
Node* current = update[0]->forward[0];
if (current && current->value == value) {
for (int i = 0; i <= currentLevel; i++) {
if (update[i]->forward[i] != current) {
break;
}
update[i]->forward[i] = current->forward[i];
}
delete current;
while (currentLevel > 0 && header->forward[currentLevel] == nullptr) {
currentLevel--;
}
}
}
/**
* @brief 显示跳表的内容
*/
void display() {
for (int i = currentLevel; i >= 0; i--) {
Node* node = header->forward[i];
std::cout << "Level " << i << ": ";
while (node) {
std::cout << node->value << " ";
node = node->forward[i];
}
std::cout << std::endl;
}
}
};
int main() {
SkipList list(5, 0.5);
list.insert(3);
list.insert(6);
list.insert(7);
list.insert(9);
list.insert(12);
list.insert(19);
list.insert(17);
list.insert(26);
list.insert(21);
list.insert(25);
std::cout << "SkipList after insertion:" << std::endl;
list.display();
std::cout << "Search for 19: " << (list.search(19) ? "Found" : "Not Found") << std::endl;
std::cout << "Search for 15: " << (list.search(15) ? "Found" : "Not Found") << std::endl;
list.remove(19);
std::cout << "SkipList after removing 19:" << std::endl;
list.display();
return 0;
}