mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-07-04 11:27:16 -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