目录
链表中的结点用存储单元(若干个连续字节)来存放,存储单元之间既可以是(存储空间上)连续的,也可以是不连续的,甚至可以零散地分布在存储空间中的任何位置。换言之,链表中结点的逻辑次序和物理次序之间并无必然联系。最重要的是,链表可以在不移动结点位置的前提下根据需要随时添加删除结点,动态调整。

数据结构_QomolangmaH的博客-CSDN博客
https://blog.csdn.net/m0_63834988/category_12435965.html
增加了向前指针的链表叫作跳表。跳表全称叫做跳跃表,简称跳表。跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。跳表不仅能提高搜索性能,同时也可以提高插入和删除操作的性能。

跳表是一个随机化的数据结构,可以被看做二叉树的一个变种,它的性能在某些情况下可以与平衡二叉树(如红黑树和AVL树)相媲美,它的查找、插入和删除操作的时间复杂度为O(log n)
跳表的原理相对简单,因此在一些具有内存限制或对插入和删除操作性能要求较高的场景下,跳表是一种常用的选择。例如,Redis和LevelDB等数据库系统中就广泛使用了跳表来实现有序集合的功能。

定义宏:
#define MAX_LEVEL 6
- typedef struct SkipListNode {
- int key;
- int value;
- struct SkipListNode** forward;
- } SkipListNode;
SkipListNode表示跳表中的节点,包含一个整型的键值key和一个整型的值value,以及一个指向其他节点的指针数组forward
- typedef struct SkipList {
- int max_level;
- int level;
- SkipListNode* header;
- } SkipList;
SkipList表示整个跳表,包含最大层数max_level、当前层数level和一个指向头节点的指针header。
- SkipListNode* skipListNodeInit(int level, int key, int value) {
- SkipListNode* node = (SkipListNode*)malloc(sizeof(SkipListNode));
- node->key = key;
- node->value = value;
- node->forward = (SkipListNode**)malloc((level + 1) * sizeof(SkipListNode*));
- for (int i = 0; i <= level; i++) {
- node->forward[i] = NULL;
- }
- return node;
- }
level、键值key和值value作为参数,并动态分配内存来创建节点;forward分配足够的内存;- SkipList* skipListInit() {
- SkipList* skipList = (SkipList*)malloc(sizeof(SkipList));
- skipList->max_level = MAX_LEVEL;
- skipList->level = 0;
- skipList->header = skipListNodeInit(MAX_LEVEL, 0, 0);
- for (int i = 0; i <= MAX_LEVEL; i++) {
- skipList->header->forward[i] = NULL;
- }
- return skipList;
- }
SkipList结构体max_level为预定义的常量值MAX_LEVELlevel为0skipListNodeInit函数创建一个头节点。- int randomLevel() {
- int level = 1;
- while (rand() < RAND_MAX / 2 && level < MAX_LEVEL) {
- level++;
- }
- return level;
- }
rand函数生成一个伪随机数,并与RAND_MAX的一半进行比较。如果生成的数小于RAND_MAX的一半,并且层数小于最大层数MAX_LEVEL,则层数加1。- SkipListNode* skipListSearch(SkipList* skipList, int key) {
- SkipListNode* current = skipList->header;
- for (int i = skipList->level; i >= 0; i--) {
- while (current->forward[i] != NULL && current->forward[i]->key < key) {
- current = current->forward[i];
- }
- }
- current = current->forward[0];
- if (current != NULL && current->key == key) {
- return current;
- } else {
- return NULL;
- }
- }
从跳表的最高层开始遍历节点,找到在每一层中键值小于给定键值的最大节点。然后,沿着最底层的指针找到当前节点,并检查是否存在具有相同键值的节点。如果存在,返回该节点的指针。否则,返回NULL表示未找到。
- void skipListInsert(SkipList* skipList, int key, int value) {
- SkipListNode* update[MAX_LEVEL + 1];
- SkipListNode* current = skipList->header;
- for (int i = skipList->level; i >= 0; i--) {
- while (current->forward[i] != NULL && current->forward[i]->key < key) {
- current = current->forward[i];
- }
- update[i] = current;
- }
- current = current->forward[0];
- if (current != NULL && current->key == key) {
- current->value = value;
- } else {
- int new_level = randomLevel();
- if (new_level > skipList->level) {
- for (int i = skipList->level + 1; i <= new_level; i++) {
- update[i] = skipList->header;
- }
- skipList->level = new_level;
- }
- SkipListNode* new_node = skipListNodeInit(new_level, key, value);
- for (int i = 0; i <= new_level; i++) {
- new_node->forward[i] = update[i]->forward[i];
- update[i]->forward[i] = new_node;
- }
- }
- }
update,用于记录在每个层级上需要更新的节点- void skipListDelete(SkipList* skipList, int key) {
- SkipListNode* update[MAX_LEVEL + 1];
- SkipListNode* current = skipList->header;
- for (int i = skipList->level; i >= 0; i--) {
- while (current->forward[i] != NULL && current->forward[i]->key < key) {
- current = current->forward[i];
- }
- update[i] = current;
- }
- current = current->forward[0];
- if (current != NULL && current->key == key) {
- for (int i = 0; i <= skipList->level; i++) {
- if (update[i]->forward[i] != current) {
- break;
- }
- update[i]->forward[i] = current->forward[i];
- }
- free(current);
- while (skipList->level > 0 && skipList->header->forward[skipList->level] == NULL) {
- skipList->level--;
- }
- }
- }
update,用于记录在每个层级上需要更新的节点。- int main() {
- srand(time(NULL));
- SkipList* skipList = skipListInit();
-
- skipListInsert(skipList, 3, 30);
- skipListInsert(skipList, 1, 10);
- skipListInsert(skipList, 2, 20);
- skipListInsert(skipList, 4, 40);
- skipListInsert(skipList, 6, 60);
- skipListInsert(skipList, 5, 50);
- skipListInsert(skipList, 7, 70);
-
- SkipListNode* node = skipListSearch(skipList, 4);
- if (node != NULL) {
- printf("Key: %d, Value: %d\n", node->key, node->value);
- } else {
- printf("Key not found.\n");
- }
-
- skipListDelete(skipList, 4);
-
- node = skipListSearch(skipList, 4);
- if (node != NULL) {
- printf("Key: %d, Value: %d\n", node->key, node->value);
- } else {
- printf("Key not found.\n");
- }
-
- return 0;
- }
srand函数设置随机数种子skipListInit函数初始化一个跳表skipListInsert函数插入一系列键值对skipListSearch函数搜索具有键值为4的节点,并打印出节点的键值和值。skipListDelete函数删除具有键值为4的节点。skipListSearch函数搜索具有键值为4的节点,并打印出结果。
- #include
- #include
- #include
-
- #define MAX_LEVEL 6
-
- typedef struct SkipListNode {
- int key;
- int value;
- struct SkipListNode** forward;
- } SkipListNode;
-
- typedef struct SkipList {
- int max_level;
- int level;
- SkipListNode* header;
- } SkipList;
-
- SkipListNode* skipListNodeInit(int level, int key, int value) {
- SkipListNode* node = (SkipListNode*)malloc(sizeof(SkipListNode));
- node->key = key;
- node->value = value;
- node->forward = (SkipListNode**)malloc((level + 1) * sizeof(SkipListNode*));
- for (int i = 0; i <= level; i++) {
- node->forward[i] = NULL;
- }
- return node;
- }
-
- SkipList* skipListInit() {
- SkipList* skipList = (SkipList*)malloc(sizeof(SkipList));
- skipList->max_level = MAX_LEVEL;
- skipList->level = 0;
- skipList->header = skipListNodeInit(MAX_LEVEL, 0, 0);
- for (int i = 0; i <= MAX_LEVEL; i++) {
- skipList->header->forward[i] = NULL;
- }
- return skipList;
- }
-
- int randomLevel() {
- int level = 1;
- while (rand() < RAND_MAX / 2 && level < MAX_LEVEL) {
- level++;
- }
- return level;
- }
-
- void skipListInsert(SkipList* skipList, int key, int value) {
- SkipListNode* update[MAX_LEVEL + 1];
- SkipListNode* current = skipList->header;
- for (int i = skipList->level; i >= 0; i--) {
- while (current->forward[i] != NULL && current->forward[i]->key < key) {
- current = current->forward[i];
- }
- update[i] = current;
- }
- current = current->forward[0];
- if (current != NULL && current->key == key) {
- current->value = value;
- } else {
- int new_level = randomLevel();
- if (new_level > skipList->level) {
- for (int i = skipList->level + 1; i <= new_level; i++) {
- update[i] = skipList->header;
- }
- skipList->level = new_level;
- }
- SkipListNode* new_node = skipListNodeInit(new_level, key, value);
- for (int i = 0; i <= new_level; i++) {
- new_node->forward[i] = update[i]->forward[i];
- update[i]->forward[i] = new_node;
- }
- }
- }
-
- void skipListDelete(SkipList* skipList, int key) {
- SkipListNode* update[MAX_LEVEL + 1];
- SkipListNode* current = skipList->header;
- for (int i = skipList->level; i >= 0; i--) {
- while (current->forward[i] != NULL && current->forward[i]->key < key) {
- current = current->forward[i];
- }
- update[i] = current;
- }
- current = current->forward[0];
- if (current != NULL && current->key == key) {
- for (int i = 0; i <= skipList->level; i++) {
- if (update[i]->forward[i] != current) {
- break;
- }
- update[i]->forward[i] = current->forward[i];
- }
- free(current);
- while (skipList->level > 0 && skipList->header->forward[skipList->level] == NULL) {
- skipList->level--;
- }
- }
- }
-
- SkipListNode* skipListSearch(SkipList* skipList, int key) {
- SkipListNode* current = skipList->header;
- for (int i = skipList->level; i >= 0; i--) {
- while (current->forward[i] != NULL && current->forward[i]->key < key) {
- current = current->forward[i];
- }
- }
- current = current->forward[0];
- if (current != NULL && current->key == key) {
- return current;
- } else {
- return NULL;
- }
- }
-
- int main() {
- srand(time(NULL));
- SkipList* skipList = skipListInit();
-
- skipListInsert(skipList, 3, 30);
- skipListInsert(skipList, 1, 10);
- skipListInsert(skipList, 2, 20);
- skipListInsert(skipList, 4, 40);
- skipListInsert(skipList, 6, 60);
- skipListInsert(skipList, 5, 50);
- skipListInsert(skipList, 7, 70);
-
- SkipListNode* node = skipListSearch(skipList, 4);
- if (node != NULL) {
- printf("Key: %d, Value: %d\n", node->key, node->value);
- } else {
- printf("Key not found.\n");
- }
-
- skipListDelete(skipList, 4);
-
- node = skipListSearch(skipList, 4);
- if (node != NULL) {
- printf("Key: %d, Value: %d\n", node->key, node->value);
- } else {
- printf("Key not found.\n");
- }
-
- return 0;
- }