libdict
Data Structure C Library
Loading...
Searching...
No Matches
skiplist.c
Go to the documentation of this file.
1/*
2 * libdict -- skiplist implementation.
3 *
4 * Copyright (c) 2001-2014, Farooq Mela
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * cf. [Pugh 1990], [Sedgewick 1998]
30 */
31
32#include "skiplist.h"
33
34#include <string.h> /* For memset() */
35#include "dict_private.h"
36
37typedef struct skip_node skip_node;
38
39struct skip_node {
40 void* key;
41 void* datum;
43 unsigned link_count;
45};
46
47#define MAX_LINK 32
48
56
61
62static const dict_vtable skiplist_vtable = {
63 true,
75 (dict_select_func) NULL,
78};
79
80static const itor_vtable skiplist_itor_vtable = {
99};
100
101static inline skip_node* node_new(void* key, unsigned link_count);
102static inline void node_insert(skiplist* list, skip_node* x, skip_node** update);
103static inline skip_node* node_search(skiplist* list, const void* key);
104static inline skip_node* node_search_le(skiplist* list, const void* key);
105static inline skip_node* node_search_lt(skiplist* list, const void* key);
106static inline skip_node* node_search_ge(skiplist* list, const void* key);
107static inline skip_node* node_search_gt(skiplist* list, const void* key);
108static inline unsigned rand_link_count(skiplist* list);
109
111skiplist_new(dict_compare_func cmp_func, unsigned max_link)
112{
113 ASSERT(cmp_func != NULL);
114 ASSERT(max_link > 0);
115
116 if (max_link > MAX_LINK)
117 max_link = MAX_LINK;
118
119 skiplist* list = MALLOC(sizeof(*list));
120 if (list) {
121 if (!(list->head = node_new(NULL, max_link))) {
122 FREE(list);
123 return NULL;
124 }
125
126 list->max_link = max_link;
127 list->top_link = 0;
128 list->cmp_func = cmp_func;
129 list->count = 0;
130 }
131 return list;
132}
133
134dict*
135skiplist_dict_new(dict_compare_func cmp_func, unsigned max_link)
136{
137 dict* dct = MALLOC(sizeof(*dct));
138 if (dct) {
139 if (!(dct->_object = skiplist_new(cmp_func, max_link))) {
140 FREE(dct);
141 return NULL;
142 }
143 dct->_vtable = &skiplist_vtable;
144 }
145 return dct;
146}
147
148size_t
150{
151 size_t count = skiplist_clear(list, delete_func);
152 FREE(list->head);
153 FREE(list);
154 return count;
155}
156
157static inline void
158node_insert(skiplist* list, skip_node* x, skip_node** update)
159{
160 const unsigned nlinks = x->link_count;
161 ASSERT(nlinks < list->max_link);
162
163 if (list->top_link < nlinks) {
164 for (unsigned k = list->top_link+1; k <= nlinks; k++) {
165 ASSERT(!update[k]);
166 update[k] = list->head;
167 }
168 list->top_link = nlinks;
169 }
170
171 x->prev = (update[0] == list->head) ? NULL : update[0];
172 if (update[0]->link[0])
173 update[0]->link[0]->prev = x;
174 for (unsigned k = 0; k < nlinks; k++) {
175 ASSERT(update[k]->link_count > k);
176 x->link[k] = update[k]->link[k];
177 update[k]->link[k] = x;
178 }
179 ++list->count;
180}
181
183skiplist_insert(skiplist* list, void* key)
184{
185 skip_node* x = list->head;
186 skip_node* update[MAX_LINK] = { 0 };
187 for (unsigned k = list->top_link+1; k-->0; ) {
188 ASSERT(x->link_count > k);
189 for (;;) {
190 skip_node* const y = x->link[k];
191 if (!y)
192 break;
193 const int cmp = list->cmp_func(key, y->key);
194 if (cmp < 0) {
195 while (k > 0 && x->link[k - 1] == y)
196 update[k--] = x;
197 break;
198 } else if (cmp == 0)
199 return (dict_insert_result) { &y->datum, false };
200 x = y;
201 }
202 update[k] = x;
203 }
204
205 x = node_new(key, rand_link_count(list));
206 if (!x)
207 return (dict_insert_result) { NULL, false };
208 node_insert(list, x, update);
209 return (dict_insert_result) { &x->datum, true };
210}
211
212static inline skip_node*
213node_search(skiplist* list, const void* key)
214{
215 skip_node* x = list->head;
216 for (unsigned k = list->top_link+1; k-->0;) {
217 for (;;) {
218 skip_node* const y = x->link[k];
219 if (!y)
220 break;
221 const int cmp = list->cmp_func(key, y->key);
222 if (cmp < 0) {
223 while (k > 0 && x->link[k - 1] == y)
224 k--;
225 break;
226 } else if (cmp == 0)
227 return y;
228 x = y;
229 }
230 }
231 return NULL;
232}
233
234static inline skip_node*
235node_search_le(skiplist* list, const void* key)
236{
237 skip_node* x = list->head;
238 for (unsigned k = list->top_link+1; k-->0;) {
239 for (;;) {
240 skip_node* const y = x->link[k];
241 if (!y)
242 break;
243 const int cmp = list->cmp_func(key, y->key);
244 if (cmp < 0) {
245 while (k > 0 && x->link[k - 1] == y)
246 k--;
247 break;
248 } else if (cmp == 0)
249 return y;
250 x = y;
251 }
252 }
253 return x == list->head ? NULL : x;
254}
255
256static inline skip_node*
257node_search_lt(skiplist* list, const void* key)
258{
259 skip_node* x = list->head;
260 for (unsigned k = list->top_link+1; k-->0;) {
261 for (;;) {
262 skip_node* const y = x->link[k];
263 if (!y)
264 break;
265 const int cmp = list->cmp_func(key, y->key);
266 if (cmp < 0) {
267 while (k > 0 && x->link[k - 1] == y)
268 k--;
269 break;
270 } else if (cmp == 0)
271 return y->prev;
272 x = y;
273 }
274 }
275 return x == list->head ? NULL : x;
276}
277
278static inline skip_node*
279node_search_ge(skiplist* list, const void* key)
280{
281 skip_node* x = list->head;
282 skip_node* ret = NULL;
283 for (unsigned k = list->top_link+1; k-->0;) {
284 for (;;) {
285 skip_node* const y = x->link[k];
286 if (!y)
287 break;
288 const int cmp = list->cmp_func(key, y->key);
289 if (cmp < 0) {
290 ret = y;
291 while (k > 0 && x->link[k - 1] == y)
292 k--;
293 break;
294 } else if (cmp == 0)
295 return y;
296 x = y;
297 }
298 }
299 return ret;
300}
301
302static inline skip_node*
303node_search_gt(skiplist* list, const void* key)
304{
305 skip_node* x = list->head;
306 skip_node* ret = NULL;
307 for (unsigned k = list->top_link+1; k-->0;) {
308 for (;;) {
309 skip_node* const y = x->link[k];
310 if (!y)
311 break;
312 const int cmp = list->cmp_func(key, y->key);
313 if (cmp < 0) {
314 ret = y;
315 while (k > 0 && x->link[k - 1] == y)
316 k--;
317 break;
318 } else if (cmp == 0)
319 return y->link[0];
320 x = y;
321 }
322 }
323 return ret;
324}
325
326void**
327skiplist_search(skiplist* list, const void* key)
328{
329 skip_node* x = node_search(list, key);
330 return x ? &x->datum : NULL;
331}
332
333void**
334skiplist_search_le(skiplist* list, const void* key)
335{
336 skip_node* x = node_search_le(list, key);
337 return x ? &x->datum : NULL;
338}
339
340void**
341skiplist_search_lt(skiplist* list, const void* key)
342{
343 skip_node* x = node_search_lt(list, key);
344 return x ? &x->datum : NULL;
345}
346
347void**
348skiplist_search_ge(skiplist* list, const void* key)
349{
350 skip_node* x = node_search_ge(list, key);
351 return x ? &x->datum : NULL;
352}
353
354void**
355skiplist_search_gt(skiplist* list, const void* key)
356{
357 skip_node* x = node_search_gt(list, key);
358 return x ? &x->datum : NULL;
359}
360
362skiplist_remove(skiplist* list, const void* key)
363{
364 skip_node* x = list->head;
365 skip_node* update[MAX_LINK] = { 0 };
366 bool found = false;
367 for (unsigned k = list->top_link+1; k-->0;) {
368 ASSERT(x->link_count > k);
369 for (;;) {
370 skip_node* const y = x->link[k];
371 if (!y)
372 break;
373 const int cmp = list->cmp_func(key, y->key);
374 if (cmp > 0)
375 x = y;
376 else {
377 while (k > 0 && x->link[k - 1] == y)
378 update[k--] = x;
379 if (cmp == 0)
380 found = true;
381 break;
382 }
383 }
384 update[k] = x;
385 }
386 if (!found)
387 return (dict_remove_result) { NULL, NULL, false };
388 x = x->link[0];
389 for (unsigned k = 0; k <= list->top_link; k++) {
390 ASSERT(update[k] != NULL);
391 ASSERT(update[k]->link_count > k);
392 if (update[k]->link[k] != x) break;
393 update[k]->link[k] = x->link[k];
394 }
395 if (x->prev)
396 x->prev->link[0] = x->link[0];
397 if (x->link[0])
398 x->link[0]->prev = x->prev;
399 dict_remove_result result = { x->key, x->datum, true };
400 FREE(x);
401 while (list->top_link > 0 && !list->head->link[list->top_link-1])
402 list->top_link--;
403 list->count--;
404 return result;
405}
406
407size_t
409{
410 skip_node* node = list->head->link[0];
411 while (node) {
412 skip_node* next = node->link[0];
413 if (delete_func) delete_func(node->key, node->datum);
414 FREE(node);
415 node = next;
416 }
417
418 const size_t count = list->count;
419 list->count = 0;
420 list->head->link[list->top_link] = NULL;
421 while (list->top_link)
422 list->head->link[--list->top_link] = NULL;
423
424 return count;
425}
426
427size_t
428skiplist_traverse(skiplist* list, dict_visit_func visit, void* user_data)
429{
430 size_t count = 0;
431 for (skip_node* node = list->head->link[0]; node; node = node->link[0]) {
432 ++count;
433 if (!visit(node->key, node->datum, user_data)) break;
434 }
435 return count;
436}
437
438size_t
440{
441 return list->count;
442}
443
444bool
446{
447 if (list->count == 0) {
448 VERIFY(list->top_link == 0);
449 } else {
450 VERIFY(list->top_link > 0);
451 }
452 VERIFY(list->top_link < list->max_link);
453 for (unsigned i = 0; i < list->top_link; ++i) {
454 VERIFY(list->head->link[i] != NULL);
455 }
456 for (unsigned i = list->top_link; i < list->max_link; ++i) {
457 VERIFY(list->head->link[i] == NULL);
458 }
459 unsigned observed_top_link = 0;
460
461 skip_node* prev = NULL;
462 skip_node* node = list->head->link[0];
463 while (node) {
464 if (observed_top_link < node->link_count)
465 observed_top_link = node->link_count;
466
467 VERIFY(node->prev == prev);
468 VERIFY(node->link_count >= 1);
469 VERIFY(node->link_count <= list->top_link);
470 for (unsigned k = 0; k < node->link_count; k++) {
471 if (node->link[k]) {
472 VERIFY(node->link[k]->link_count >= k);
473 }
474 }
475
476 prev = node;
477 node = node->link[0];
478 }
479 VERIFY(list->top_link == observed_top_link);
480 return true;
481}
482
483size_t
484skiplist_link_count_histogram(const skiplist* list, size_t counts[], size_t ncounts)
485{
486 for (size_t i = 0; i < ncounts; ++i)
487 counts[i] = 0;
488
489 size_t max_num_links = 0;
490 for (const skip_node* node = list->head->link[0]; node; node = node->link[0]) {
491 if (max_num_links < node->link_count)
492 max_num_links = node->link_count;
493 if (ncounts > node->link_count)
494 counts[node->link_count]++;
495 }
496 return max_num_links;
497}
498
501{
502 skiplist_itor* itor = MALLOC(sizeof(*itor));
503 if (itor) {
504 itor->list = list;
505 itor->node = NULL;
506 }
507 return itor;
508}
509
512{
513 dict_itor* itor = MALLOC(sizeof(*itor));
514 if (itor) {
515 if (!(itor->_itor = skiplist_itor_new(list))) {
516 FREE(itor);
517 return NULL;
518 }
519 itor->_vtable = &skiplist_itor_vtable;
520 }
521 return itor;
522}
523
524void
526{
527 FREE(itor);
528}
529
530bool
532{
533 return itor->node != NULL;
534}
535
536void
538{
539 itor->node = NULL;
540}
541
542bool
544{
545 if (itor->node)
546 itor->node = itor->node->link[0];
547 return itor->node != NULL;
548}
549
550bool
552{
553 if (itor->node)
554 itor->node = itor->node->prev;
555 return itor->node != NULL;
556}
557
558bool
560{
561 while (count--)
562 if (!skiplist_itor_next(itor))
563 return false;
564 return itor->node != NULL;
565}
566
567bool
569{
570 while (count--)
571 if (!skiplist_itor_prev(itor))
572 return false;
573 return itor->node != NULL;
574}
575
576bool
578{
579 return (itor->node = itor->list->head->link[0]) != NULL;
580}
581
582bool
584{
585 skip_node* x = itor->list->head;
586 for (unsigned k = itor->list->top_link; k-->0;) {
587 while (x->link[k])
588 x = x->link[k];
589 }
590 if (x == itor->list->head) {
591 itor->node = NULL;
592 return false;
593 } else {
594 itor->node = x;
595 return true;
596 }
597}
598
599bool
600skiplist_itor_search(skiplist_itor* itor, const void* key)
601{
602 return (itor->node = node_search(itor->list, key)) != NULL;
603}
604
605bool
607{
608 return (itor->node = node_search_le(itor->list, key)) != NULL;
609}
610
611bool
613{
614 return (itor->node = node_search_lt(itor->list, key)) != NULL;
615}
616
617bool
619{
620 return (itor->node = node_search_ge(itor->list, key)) != NULL;
621}
622
623bool
625{
626 return (itor->node = node_search_gt(itor->list, key)) != NULL;
627}
628
629const void*
631{
632 return itor->node ? itor->node->key : NULL;
633}
634
635void**
637{
638 return itor->node ? &itor->node->datum : NULL;
639}
640
641int
643{
644 ASSERT(itor1->list == itor2->list);
645 if (!itor1->node)
646 return !itor2->node ? 0 : -1;
647 if (!itor2->node)
648 return 1;
649 return itor1->list->cmp_func(itor1->node->key, itor2->node->key);
650}
651
652bool
654{
655 if (!itor->node)
656 return false;
657 /* XXX make this smarter */
658 dict_remove_result result = skiplist_remove(itor->list, itor->node->key);
659 ASSERT(result.removed);
660 itor->node = NULL;
661 return true;
662}
663
664static inline skip_node*
665node_new(void* key, unsigned link_count)
666{
667 ASSERT(link_count >= 1);
668
669 skip_node* node = MALLOC(sizeof(*node) +
670 sizeof(node->link[0]) * link_count);
671 if (node) {
672 node->key = key;
673 node->datum = NULL;
674 node->prev = NULL;
675 node->link_count = link_count;
676 memset(node->link, 0, sizeof(node->link[0]) * link_count);
677 }
678 return node;
679}
680
681static inline unsigned
682rand_link_count(skiplist* list)
683{
684 unsigned count = (unsigned) __builtin_ctz(dict_rand()) / 2 + 1;
685 return (count >= list->max_link) ? list->max_link - 1 : count;
686}
dict_remove_result(* dict_remove_func)(void *obj, const void *key)
Definition dict.h:90
int(* dict_compare_func)(const void *, const void *)
Definition dict.h:54
bool(* dict_select_func)(void *obj, size_t n, const void **key, void **datum)
Definition dict.h:93
void(* dict_invalidate_func)(void *itor)
Definition dict.h:117
size_t(* dict_traverse_func)(void *obj, dict_visit_func visit, void *user_data)
Definition dict.h:92
dict_insert_result(* dict_insert_func)(void *obj, void *key)
Definition dict.h:87
void(* dict_delete_func)(void *, void *)
Definition dict.h:57
int(* dict_icompare_func)(void *itor1, void *itor2)
Definition dict.h:128
bool(* dict_nextn_func)(void *itor, size_t count)
Definition dict.h:120
bool(* dict_valid_func)(const void *itor)
Definition dict.h:116
size_t(* dict_count_func)(const void *obj)
Definition dict.h:94
bool(* dict_first_func)(void *itor)
Definition dict.h:122
bool(* dict_next_func)(void *itor)
Definition dict.h:118
void *(* dict_key_func)(void *itor)
Definition dict.h:124
size_t(* dict_dfree_func)(void *obj, dict_delete_func delete_func)
Definition dict.h:85
void **(* dict_datum_func)(void *itor)
Definition dict.h:125
bool(* dict_prevn_func)(void *itor, size_t count)
Definition dict.h:121
void **(* dict_search_func)(void *obj, const void *key)
Definition dict.h:88
bool(* dict_isearch_func)(void *itor, const void *key)
Definition dict.h:126
bool(* dict_iremove_func)(void *itor)
Definition dict.h:127
bool(* dict_prev_func)(void *itor)
Definition dict.h:119
dict_itor *(* dict_inew_func)(void *obj)
Definition dict.h:84
bool(* dict_last_func)(void *itor)
Definition dict.h:123
bool(* dict_verify_func)(const void *obj)
Definition dict.h:95
bool(* dict_visit_func)(const void *, void *, void *)
Definition dict.h:59
size_t(* dict_clear_func)(void *obj, dict_delete_func delete_func)
Definition dict.h:91
void(* dict_ifree_func)(void *itor)
Definition dict.h:115
#define FREE(p)
#define ASSERT(expr)
#define VERIFY(expr)
#define MALLOC(n)
bool skiplist_itor_search_le(skiplist_itor *itor, const void *key)
Definition skiplist.c:606
size_t skiplist_traverse(skiplist *list, dict_visit_func visit, void *user_data)
Definition skiplist.c:428
skiplist * skiplist_new(dict_compare_func cmp_func, unsigned max_link)
Definition skiplist.c:111
bool skiplist_itor_search_gt(skiplist_itor *itor, const void *key)
Definition skiplist.c:624
bool skiplist_itor_remove(skiplist_itor *itor)
Definition skiplist.c:653
void ** skiplist_search_le(skiplist *list, const void *key)
Definition skiplist.c:334
void ** skiplist_search(skiplist *list, const void *key)
Definition skiplist.c:327
bool skiplist_itor_search(skiplist_itor *itor, const void *key)
Definition skiplist.c:600
bool skiplist_verify(const skiplist *list)
Definition skiplist.c:445
bool skiplist_itor_first(skiplist_itor *itor)
Definition skiplist.c:577
bool skiplist_itor_next(skiplist_itor *itor)
Definition skiplist.c:543
bool skiplist_itor_prevn(skiplist_itor *itor, size_t count)
Definition skiplist.c:568
size_t skiplist_free(skiplist *list, dict_delete_func delete_func)
Definition skiplist.c:149
void skiplist_itor_invalidate(skiplist_itor *itor)
Definition skiplist.c:537
const void * skiplist_itor_key(const skiplist_itor *itor)
Definition skiplist.c:630
void ** skiplist_search_gt(skiplist *list, const void *key)
Definition skiplist.c:355
bool skiplist_itor_search_lt(skiplist_itor *itor, const void *key)
Definition skiplist.c:612
bool skiplist_itor_valid(const skiplist_itor *itor)
Definition skiplist.c:531
dict * skiplist_dict_new(dict_compare_func cmp_func, unsigned max_link)
Definition skiplist.c:135
void ** skiplist_search_ge(skiplist *list, const void *key)
Definition skiplist.c:348
bool skiplist_itor_search_ge(skiplist_itor *itor, const void *key)
Definition skiplist.c:618
int skiplist_itor_compare(const skiplist_itor *itor1, const skiplist_itor *itor2)
Definition skiplist.c:642
void ** skiplist_itor_datum(skiplist_itor *itor)
Definition skiplist.c:636
dict_itor * skiplist_dict_itor_new(skiplist *list)
Definition skiplist.c:511
void ** skiplist_search_lt(skiplist *list, const void *key)
Definition skiplist.c:341
#define MAX_LINK
Definition skiplist.c:47
void skiplist_itor_free(skiplist_itor *itor)
Definition skiplist.c:525
dict_insert_result skiplist_insert(skiplist *list, void *key)
Definition skiplist.c:183
bool skiplist_itor_nextn(skiplist_itor *itor, size_t count)
Definition skiplist.c:559
skiplist_itor * skiplist_itor_new(skiplist *list)
Definition skiplist.c:500
size_t skiplist_clear(skiplist *list, dict_delete_func delete_func)
Definition skiplist.c:408
size_t skiplist_count(const skiplist *list)
Definition skiplist.c:439
dict_remove_result skiplist_remove(skiplist *list, const void *key)
Definition skiplist.c:362
bool skiplist_itor_last(skiplist_itor *itor)
Definition skiplist.c:583
size_t skiplist_link_count_histogram(const skiplist *list, size_t counts[], size_t ncounts)
Definition skiplist.c:484
bool skiplist_itor_prev(skiplist_itor *itor)
Definition skiplist.c:551
void * _itor
Definition dict.h:175
const itor_vtable * _vtable
Definition dict.h:176
Definition dict.h:151
void * _object
Definition dict.h:152
const dict_vtable * _vtable
Definition dict.h:153
skip_node * prev
Definition skiplist.c:42
void * datum
Definition skiplist.c:41
void * key
Definition skiplist.c:40
unsigned link_count
Definition skiplist.c:43
skip_node * link[]
Definition skiplist.c:44
skiplist * list
Definition skiplist.c:58
skip_node * node
Definition skiplist.c:59
skip_node * head
Definition skiplist.c:50
unsigned max_link
Definition skiplist.c:51
dict_compare_func cmp_func
Definition skiplist.c:53
size_t count
Definition skiplist.c:54
unsigned top_link
Definition skiplist.c:52