mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-07-04 19:37:15 -04:00
Add Skip List implementation and unit test
This commit is contained in:
parent
7225fbcbb9
commit
44ca6d9ec8
77
skip_list.c
Normal file
77
skip_list.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include "skip_list.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static int xRandomLevel(void) {
|
||||||
|
int level = 1;
|
||||||
|
while ((rand() & 0x1) && level < SKIP_LIST_MAX_LEVEL)
|
||||||
|
level++;
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vSkipListInit(SkipList_t *list) {
|
||||||
|
list->level = 1;
|
||||||
|
list->header = (SkipListNode_t *)calloc(1, sizeof(SkipListNode_t));
|
||||||
|
for (int i = 0; i < SKIP_LIST_MAX_LEVEL; i++)
|
||||||
|
list->header->forward[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vSkipListInsert(SkipList_t *list, TickType_t key, void *value) {
|
||||||
|
SkipListNode_t *update[SKIP_LIST_MAX_LEVEL];
|
||||||
|
SkipListNode_t *x = list->header;
|
||||||
|
for (int i = list->level - 1; i >= 0; i--) {
|
||||||
|
while (x->forward[i] && x->forward[i]->key < key)
|
||||||
|
x = x->forward[i];
|
||||||
|
update[i] = x;
|
||||||
|
}
|
||||||
|
x = x->forward[0];
|
||||||
|
if (x && x->key == key) {
|
||||||
|
x->value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int lvl = xRandomLevel();
|
||||||
|
if (lvl > list->level) {
|
||||||
|
for (int i = list->level; i < lvl; i++)
|
||||||
|
update[i] = list->header;
|
||||||
|
list->level = lvl;
|
||||||
|
}
|
||||||
|
x = (SkipListNode_t *)calloc(1, sizeof(SkipListNode_t));
|
||||||
|
x->key = key;
|
||||||
|
x->value = value;
|
||||||
|
for (int i = 0; i < lvl; i++) {
|
||||||
|
x->forward[i] = update[i]->forward[i];
|
||||||
|
update[i]->forward[i] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vSkipListRemove(SkipList_t *list, TickType_t key) {
|
||||||
|
SkipListNode_t *update[SKIP_LIST_MAX_LEVEL];
|
||||||
|
SkipListNode_t *x = list->header;
|
||||||
|
for (int i = list->level - 1; i >= 0; i--) {
|
||||||
|
while (x->forward[i] && x->forward[i]->key < key)
|
||||||
|
x = x->forward[i];
|
||||||
|
update[i] = x;
|
||||||
|
}
|
||||||
|
x = x->forward[0];
|
||||||
|
if (x && x->key == key) {
|
||||||
|
for (int i = 0; i < list->level; i++) {
|
||||||
|
if (update[i]->forward[i] != x)
|
||||||
|
break;
|
||||||
|
update[i]->forward[i] = x->forward[i];
|
||||||
|
}
|
||||||
|
free(x);
|
||||||
|
while (list->level > 1 && list->header->forward[list->level - 1] == NULL)
|
||||||
|
list->level--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pvSkipListSearch(SkipList_t *list, TickType_t key) {
|
||||||
|
SkipListNode_t *x = list->header;
|
||||||
|
for (int i = list->level - 1; i >= 0; i--) {
|
||||||
|
while (x->forward[i] && x->forward[i]->key < key)
|
||||||
|
x = x->forward[i];
|
||||||
|
}
|
||||||
|
x = x->forward[0];
|
||||||
|
if (x && x->key == key)
|
||||||
|
return x->value;
|
||||||
|
return NULL;
|
||||||
|
}
|
32
skip_list.h
Normal file
32
skip_list.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef FREERTOS_SKIP_LIST_H
|
||||||
|
#define FREERTOS_SKIP_LIST_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef TickType_t
|
||||||
|
typedef unsigned int TickType_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SKIP_LIST_MAX_LEVEL
|
||||||
|
#define SKIP_LIST_MAX_LEVEL 4 // Tunable for memory/complexity tradeoff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
typedef struct SkipListNode {
|
||||||
|
TickType_t key;
|
||||||
|
void *value;
|
||||||
|
struct SkipListNode *forward[SKIP_LIST_MAX_LEVEL];
|
||||||
|
} SkipListNode_t;
|
||||||
|
|
||||||
|
typedef struct SkipList {
|
||||||
|
SkipListNode_t *header;
|
||||||
|
int level;
|
||||||
|
} SkipList_t;
|
||||||
|
|
||||||
|
void vSkipListInit(SkipList_t *list);
|
||||||
|
void vSkipListInsert(SkipList_t *list, TickType_t key, void *value);
|
||||||
|
void vSkipListRemove(SkipList_t *list, TickType_t key);
|
||||||
|
void *pvSkipListSearch(SkipList_t *list, TickType_t key);
|
||||||
|
|
||||||
|
#endif // FREERTOS_SKIP_LIST_H
|
62
test_skip_list.c
Normal file
62
test_skip_list.c
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "skip_list.h"
|
||||||
|
|
||||||
|
void print_skip_list(SkipList_t *list) {
|
||||||
|
printf("Skip List: ");
|
||||||
|
SkipListNode_t *node = list->header->forward[0];
|
||||||
|
while (node) {
|
||||||
|
printf("(%u, %p) ", node->key, node->value);
|
||||||
|
node = node->forward[0];
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
SkipList_t list;
|
||||||
|
vSkipListInit(&list);
|
||||||
|
|
||||||
|
// Insert test
|
||||||
|
printf("Inserting values...\n");
|
||||||
|
for (TickType_t i = 10; i > 0; --i) {
|
||||||
|
int *val = (int *)malloc(sizeof(int));
|
||||||
|
*val = i * 100;
|
||||||
|
vSkipListInsert(&list, i, val);
|
||||||
|
}
|
||||||
|
print_skip_list(&list);
|
||||||
|
|
||||||
|
// Search test
|
||||||
|
printf("Searching for key 5...\n");
|
||||||
|
int *found = (int *)pvSkipListSearch(&list, 5);
|
||||||
|
if (found) {
|
||||||
|
printf("Found key 5 with value %d\n", *found);
|
||||||
|
} else {
|
||||||
|
printf("Key 5 not found!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Searching for key 42...\n");
|
||||||
|
found = (int *)pvSkipListSearch(&list, 42);
|
||||||
|
if (found) {
|
||||||
|
printf("Found key 42 with value %d\n", *found);
|
||||||
|
} else {
|
||||||
|
printf("Key 42 not found!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove test
|
||||||
|
printf("Removing key 5...\n");
|
||||||
|
vSkipListRemove(&list, 5);
|
||||||
|
print_skip_list(&list);
|
||||||
|
found = (int *)pvSkipListSearch(&list, 5);
|
||||||
|
if (!found) {
|
||||||
|
printf("Key 5 successfully removed.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
for (TickType_t i = 1; i <= 10; ++i) {
|
||||||
|
int *val = (int *)pvSkipListSearch(&list, i);
|
||||||
|
if (val) free(val);
|
||||||
|
}
|
||||||
|
// Free header node
|
||||||
|
free(list.header);
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
test_skip_list.exe
Normal file
BIN
test_skip_list.exe
Normal file
Binary file not shown.
Loading…
Reference in a new issue