跳跃表(Skiplist)是一种可以替代平衡树的数据结构,它允许快速的插入、删除、查找操作,所有操作的平均时间复杂度都是O(logN)。在Redis中,跳跃表被广泛应用于有序集合数据类型(Sorted Set)的底层实现。
以下是一个简单的C语言实现,演示如何创建和使用一个跳跃表节点和跳跃表结构:
#include <stdio.h>
#include <stdlib.h>
typedef struct skiplistNode {
int key;
struct skiplistNode *backward;
struct skiplistNode *next[];
} skiplistNode;
typedef struct skiplist {
skiplistNode *header, *tail;
int level;
} skiplist;
// 创建一个带有特定层数的新节点
skiplistNode *createNode(int key, int level) {
skiplistNode *node = malloc(sizeof(skiplistNode) + level * sizeof(skiplistNode*));
node->key = key;
node->backward = NULL;
for (int i = 0; i < level; i++) {
node->next[i] = NULL;
}
return node;
}
// 初始化一个空的跳跃表
skiplist *initSkipList() {
skiplist *list = malloc(sizeof(skiplist));
list->header = createNode(0, 32); // 假设最大层数为32
list->tail = NULL;
list->level = 0;
return list;
}
// 插入一个新的节点
void insert(skiplist *list, int key) {
skiplistNode *update[32];
skiplistNode *node = list->header;
int level = list->level;
for (int i = level; i >= 0; i--) {
while (node->next[i] && node->next[i]->key < key) {
node = node->next[i];
}
update[i] = node;
}
if (node->next[0] && node->next[0]->key == key) {
// 键值已存在,不做操作
} else {
int newLevel = rand() % 32; // 假设随机函数返回值的范围用于决定新节点的层数
if (newLevel > level) {
for (int i = level + 1; i <= newLevel; i++) {
update[i] = list->header;
}
level = newLevel;
}
skiplistNode *newNode = createNode(key, newLevel);
for (int i = 0; i < newLevel; i++) {
newNode->next[i] = update[i]->next[i];
update[i]->next[i] = newNode;
if (update[i] == list->tail) {
list->tail = newNode;
}
}
if (level > list->level) {
list->level = level;
}
}
}
// 查找一个节点
skiplistNode *search(skiplist *list, int key) {
skiplistNode *node = list->header;
for (int i = list->level; i >= 0; i--) {
while (node->next[i] && node->next[i]->key < key) {
node = node->next[i];
}
}
if (node->next[0] && node->next[0]->key == key) {
return node->next[0];
}
return NULL;
}
// 删除一个节点
void deleteNo