[redis] skiplist
server.h 1252行
以及leetcode1206
redis skiplist
/* ZSETs use a specialized version of Skiplists */
typedef struct zskiplistNode {
sds ele;
double score;
struct zskiplistNode *backward;
struct zskiplistLevel {
struct zskiplistNode *forward;
unsigned long span;
} level[];
} zskiplistNode;
typedef struct zskiplist {
struct zskiplistNode *header, *tail;
unsigned long length;
int level;
} zskiplist;
skiplist实现(leetcode)
/*
class Skiplist {
public:
Skiplist() {
}
bool search(int target) {
}
void add(int num) {
}
bool erase(int num) {
}
};
*/
/**
* Your Skiplist object will be instantiated and called as such:
* Skiplist* obj = new Skiplist();
* bool param_1 = obj->search(target);
* obj->add(num);
* bool param_3 = obj->erase(num);
*/
class Skiplist {
constexpr static int MAXLEVEL = 8;
constexpr static int probability = RAND_MAX / 2;
struct Node {
explicit Node(int _key) : forward{}, key(_key) {}
~Node() {}
int key;
std::array<Node *, MAXLEVEL> forward;
};
public:
// 层数问题这里不需要考虑, Node节点已经考虑了这个问题
Skiplist() : curLevel(0) { header = new Node(INT_MIN); }
~Skiplist() {
Node *tmp = nullptr;
while (header != nullptr) {
tmp = header;
header = header->forward[0];
delete tmp;
}
}
static inline int randomLevel() {
int _level = 0;
while (rand() < probability && _level < MAXLEVEL - 1) {
++_level;
}
return _level;
}
void add(int num) {
std::array<Node *, MAXLEVEL> update{};
Node *current = header;
for (int i = curLevel; i >= 0; --i) {
// 这里的意思是找到第一个大于num节点的前一个节点
while (current->forward[i] != nullptr && current->forward[i]->key < num) {
// 指向下一个节点
current = current->forward[i];
}
update[i] = current; // 记录每一层最右边的小于num的节点
}
// 第0行的下一个节点, 类似的可以找到第1行, 第2行的下一个节点
// 第0行就是整个list的所有节点,
// 此时update[]记录了所有层的小于num的最右边的那个节点
current = current->forward[0];
// 如果空节点或者值不相等表示不存在该节点, 插入即可
int rlevel = randomLevel();
// 如果随机的层次更深,那么需要将我们的header节点(dummy节点)指向正确的位置(这里记录在update中,后续会更新),并更新curLevel
if (rlevel > curLevel) {
for (int i = curLevel + 1; i < rlevel + 1; ++i) {
update[i] = header;
}
curLevel = rlevel;
}
Node *newNode = new Node(num);
for (int i = 0; i <= rlevel; ++i) {
// 处理每一层的指针指向关系, 在每一层中都插入该节点
newNode->forward[i] = update[i]->forward[i];
update[i]->forward[i] = newNode;
}
}
bool erase(int num) {
std::array<Node *, MAXLEVEL> update{};
Node *current = header;
for (int i = curLevel; i >= 0; --i) {
while (current->forward[i] != nullptr && current->forward[i]->key < num) {
current = current->forward[i];
}
update[i] = current;
}
current = current->forward[0];
if (current != nullptr && current->key == num) {
for (int i = 0; i <= curLevel; ++i) {
// 自底向上删除关系节点,如果某个高层的几点的forward不是current,也就是说current节点的forward
// 只有那么高
if (update[i]->forward[i] != current) {
break;
}
update[i]->forward[i] = current->forward[i];
}
// 更新curLevel
while (curLevel > 0 && header->forward[curLevel] == nullptr) {
--curLevel;
}
delete current; // 释放内存
return true;
}
return false;
}
bool search(int num) {
Node *current = header;
for (int i = curLevel; i >= 0; --i) {
while (current->forward[i] != nullptr && current->forward[i]->key < num) {
current = current->forward[i];
}
}
current = current->forward[0];
return current != nullptr && current->key == num;
}
private:
int curLevel;
Node *header;
};