diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ca69724 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +DEBUG?= -g +CFLAGS?= -O2 -Wall -W -DSDS_ABORT_ON_OOM +CCOPT= $(CFLAGS) + +OBJ = main.o skiplist.o x.o +PRGNAME = sl + +all: sl + +# Deps (use make dep to generate this) +main.o: x.h skiplist.h x.c skiplist.c main.c +x.o: x.c x.h +skiplist.o: x.c x.h skiplist.c skiplist.h + +sl: $(OBJ) + $(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ) + +.c.o: + $(CC) -c $(CCOPT) $(DEBUG) $(COMPILE_TIME) $< + +clean: + rm -rf $(PRGNAME) *.o + +dep: + $(CC) -MM *.c diff --git a/README.rst b/README.rst index 87a4206..8be2f0b 100644 --- a/README.rst +++ b/README.rst @@ -2,3 +2,10 @@ skiplist ========= Academic example of skip list implementation in C. + +To compile just run + +.. code:: bash + + make + diff --git a/skiplist.c b/skiplist.c index 8296e7d..0060650 100644 --- a/skiplist.c +++ b/skiplist.c @@ -114,6 +114,11 @@ void sl_print(const slist *sl) #define HEAD 1 #define TAIL 0 +/* + * Repeatedly toss a coin until we get tails. + * Denote with i the number of times coin came up heads + * and return it. + */ int _toss_coin(int maxlevel) { int i; int x; @@ -135,14 +140,14 @@ int _toss_coin(int maxlevel) { } /* - * Clean top levels with only INFINITY nodes until only one such + * Remove top levels with only INFINITY nodes until only one such * level exists. */ void _sl_clean_top(slist *sl) { sl_node *foo; - for (foo = sl->topleft; foo->below != NULL; foo = foo->below) { + for (foo = sl->topleft; foo->below != NULL;) { if (foo->next->key == KEY_INF_MAX && foo->below->next->key == KEY_INF_MAX) { sl->topleft = foo->below; @@ -150,14 +155,28 @@ void _sl_clean_top(slist *sl) sl->topleft->above = NULL; sl->topright->above = NULL; --sl->maxlevel; + free(foo->data); free(foo->next); free(foo); + + foo = sl->topleft; debug("cleaned one level\n"); + } else { + break; } } } +/* + * Toss coin and get i. + * If i is greather than or equal to skip list max level then + * add one more level. + * Search for x and find the positions of the items with largest key + * less than x. + * Insert item into each level up to i. + * If key is found then just update its data. + */ int sl_add(slist *sl, int key, void *data) { sl_node *foo; @@ -190,6 +209,9 @@ int sl_add(slist *sl, int key, void *data) if (foo->below == NULL) { break; } + /* + * Save nodes that will be updated with new node. + */ update[level--] = foo; foo = foo->below; } @@ -233,6 +255,14 @@ int sl_add(slist *sl, int key, void *data) return res; } +/* + * Start at the top left position. + * At the current position compare key with node's key. + * If key is found then return it. + * If key > node's key then scan forward. + * If key < node's key then drop down. + * If we drop down past the bottom list then return NULL. + */ sl_node *sl_find(slist *sl, int key) { sl_node *foo; @@ -254,6 +284,11 @@ sl_node *sl_find(slist *sl, int key) return foo; } +/* + * Search for key and find positions with the key. + * Remove found positions. + * Remove all but one list containing only INFINITY keys. + */ int sl_remove(slist *sl, int key) { sl_node *foo;