From 890d0bf2d4e24c7853a732b59cf1b343632427bb Mon Sep 17 00:00:00 2001 From: yuqing Date: Fri, 1 Jun 2018 18:30:26 +0800 Subject: [PATCH] skiplist add function find_range --- HISTORY | 2 +- src/flat_skiplist.c | 94 ++++++++++++++++++++++++++ src/flat_skiplist.h | 2 + src/multi_skiplist.c | 77 ++++++++++++++++++++++ src/multi_skiplist.h | 2 + src/skiplist.h | 19 ++++++ src/skiplist_common.h | 2 +- src/skiplist_set.c | 79 ++++++++++++++++++++-- src/skiplist_set.h | 4 +- src/tests/test_skiplist.c | 120 ++++++++++++++++++++++++++++------ src/tests/test_skiplist_set.c | 89 ++++++++++++++++++++----- 11 files changed, 444 insertions(+), 46 deletions(-) diff --git a/HISTORY b/HISTORY index 5528cc9..39e8cd4 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,5 @@ -Version 1.38 2018-05-30 +Version 1.38 2018-06-01 * connection_pool.c: set err_no to 0 when success * shared_func.h: add functions float2buff / buff2float, double2buff / buff2double * logger.h: add function log_get_level_caption diff --git a/src/flat_skiplist.c b/src/flat_skiplist.c index 49b6d7d..28b69e6 100644 --- a/src/flat_skiplist.c +++ b/src/flat_skiplist.c @@ -221,6 +221,81 @@ static FlatSkiplistNode *flat_skiplist_get_previous(FlatSkiplist *sl, void *data return NULL; } +static FlatSkiplistNode *flat_skiplist_get_first_larger_or_equal( + FlatSkiplist *sl, void *data) +{ + int i; + int cmp; + FlatSkiplistNode *previous; + FlatSkiplistNode *current; + + previous = sl->top; + for (i=sl->top_level_index; i>=0; i--) { + while (previous->links[i] != sl->tail) { + cmp = sl->compare_func(data, previous->links[i]->data); + if (cmp > 0) { + break; + } + else if (cmp == 0) { + current = previous->links[i]->links[0]; + while ((current != sl->tail) && (sl->compare_func( + data, current->data) == 0)) + { + current = current->links[0]; + } + return current->prev; + } + + previous = previous->links[i]; + } + } + + return previous; + + /* + if (previous == sl->top) { + return sl->top; + } + else { + return previous->prev; + } + return previous->links[0]; + */ +} + +static FlatSkiplistNode *flat_skiplist_get_first_larger( + FlatSkiplist *sl, void *data) +{ + int i; + int cmp; + FlatSkiplistNode *previous; + + previous = sl->top; + for (i=sl->top_level_index; i>=0; i--) { + while (previous->links[i] != sl->tail) { + cmp = sl->compare_func(data, previous->links[i]->data); + if (cmp > 0) { + break; + } + else if (cmp == 0) { + previous = previous->links[i]->prev; + while ((previous != sl->top) && (sl->compare_func( + data, previous->data) == 0)) + { + previous = previous->prev; + } + + return previous; + } + + previous = previous->links[i]; + } + } + + return previous; + //return previous->links[0]; +} + int flat_skiplist_delete(FlatSkiplist *sl, void *data) { int i; @@ -298,3 +373,22 @@ int flat_skiplist_find_all(FlatSkiplist *sl, void *data, FlatSkiplistIterator *i iterator->current = last->prev; return 0; } + +int flat_skiplist_find_range(FlatSkiplist *sl, void *start_data, void *end_data, + FlatSkiplistIterator *iterator) +{ + if (sl->compare_func(start_data, end_data) > 0) { + iterator->current = sl->top; + iterator->top = sl->top; + return EINVAL; + } + + iterator->current = flat_skiplist_get_first_larger_or_equal(sl, start_data); + if (iterator->current == sl->top) { + iterator->top = sl->top; + return ENOENT; + } + + iterator->top = flat_skiplist_get_first_larger(sl, end_data); + return iterator->current != iterator->top ? 0 : ENOENT; +} diff --git a/src/flat_skiplist.h b/src/flat_skiplist.h index d0fe064..3100ec8 100644 --- a/src/flat_skiplist.h +++ b/src/flat_skiplist.h @@ -62,6 +62,8 @@ int flat_skiplist_delete(FlatSkiplist *sl, void *data); int flat_skiplist_delete_all(FlatSkiplist *sl, void *data, int *delete_count); void *flat_skiplist_find(FlatSkiplist *sl, void *data); int flat_skiplist_find_all(FlatSkiplist *sl, void *data, FlatSkiplistIterator *iterator); +int flat_skiplist_find_range(FlatSkiplist *sl, void *start_data, void *end_data, + FlatSkiplistIterator *iterator); static inline void flat_skiplist_iterator(FlatSkiplist *sl, FlatSkiplistIterator *iterator) { diff --git a/src/multi_skiplist.c b/src/multi_skiplist.c index b40fe5e..1f2c624 100644 --- a/src/multi_skiplist.c +++ b/src/multi_skiplist.c @@ -178,6 +178,56 @@ static MultiSkiplistNode *multi_skiplist_get_previous(MultiSkiplist *sl, void *d return NULL; } +static MultiSkiplistNode *multi_skiplist_get_first_larger_or_equal( + MultiSkiplist *sl, void *data) +{ + int i; + int cmp; + MultiSkiplistNode *previous; + + previous = sl->top; + for (i=sl->top_level_index; i>=0; i--) { + while (previous->links[i] != sl->tail) { + cmp = sl->compare_func(data, previous->links[i]->head->data); + if (cmp < 0) { + break; + } + else if (cmp == 0) { + return previous->links[i]; + } + + previous = previous->links[i]; + } + } + + return previous->links[0]; +} + +static MultiSkiplistNode *multi_skiplist_get_first_larger( + MultiSkiplist *sl, void *data) +{ + int i; + int cmp; + MultiSkiplistNode *previous; + + previous = sl->top; + for (i=sl->top_level_index; i>=0; i--) { + while (previous->links[i] != sl->tail) { + cmp = sl->compare_func(data, previous->links[i]->head->data); + if (cmp < 0) { + break; + } + else if (cmp == 0) { + return previous->links[i]->links[0]; + } + + previous = previous->links[i]; + } + } + + return previous->links[0]; +} + static inline void multi_skiplist_free_data_node(MultiSkiplist *sl, MultiSkiplistData *dataNode) { @@ -354,3 +404,30 @@ int multi_skiplist_find_all(MultiSkiplist *sl, void *data, return 0; } } + +int multi_skiplist_find_range(MultiSkiplist *sl, void *start_data, void *end_data, + MultiSkiplistIterator *iterator) +{ + if (sl->compare_func(start_data, end_data) > 0) { + iterator->current.node = sl->tail; + iterator->current.data = NULL; + iterator->tail = sl->tail; + return EINVAL; + } + + iterator->current.node = multi_skiplist_get_first_larger_or_equal(sl, start_data); + if (iterator->current.node == sl->tail) { + iterator->current.data = NULL; + iterator->tail = sl->tail; + return ENOENT; + } + + iterator->tail = multi_skiplist_get_first_larger(sl, end_data); + if (iterator->current.node != iterator->tail) { + iterator->current.data = iterator->current.node->head; + return 0; + } else { + iterator->current.data = NULL; + return ENOENT; + } +} diff --git a/src/multi_skiplist.h b/src/multi_skiplist.h index 6eb5054..75ff34c 100644 --- a/src/multi_skiplist.h +++ b/src/multi_skiplist.h @@ -73,6 +73,8 @@ int multi_skiplist_delete_all(MultiSkiplist *sl, void *data, int *delete_count); void *multi_skiplist_find(MultiSkiplist *sl, void *data); int multi_skiplist_find_all(MultiSkiplist *sl, void *data, MultiSkiplistIterator *iterator); +int multi_skiplist_find_range(MultiSkiplist *sl, void *start_data, void *end_data, + MultiSkiplistIterator *iterator); static inline void multi_skiplist_iterator(MultiSkiplist *sl, MultiSkiplistIterator *iterator) diff --git a/src/skiplist.h b/src/skiplist.h index 7d077a9..ff2b099 100644 --- a/src/skiplist.h +++ b/src/skiplist.h @@ -162,6 +162,25 @@ static inline int skiplist_find_all(Skiplist *sl, void *data, SkiplistIterator * } } +int skiplist_find_range(Skiplist *sl, void *start_data, void *end_data, + SkiplistIterator *iterator) +{ + iterator->type = sl->type; + switch (sl->type) { + case SKIPLIST_TYPE_FLAT: + return flat_skiplist_find_range(&sl->u.flat, + start_data, end_data, &iterator->u.flat); + case SKIPLIST_TYPE_MULTI: + return multi_skiplist_find_range(&sl->u.multi, + start_data, end_data, &iterator->u.multi); + case SKIPLIST_TYPE_SET: + return skiplist_set_find_range(&sl->u.set, + start_data, end_data, &iterator->u.set); + default: + return EINVAL; + } +} + static inline void skiplist_iterator(Skiplist *sl, SkiplistIterator *iterator) { iterator->type = sl->type; diff --git a/src/skiplist_common.h b/src/skiplist_common.h index 2a53aa3..41aebe9 100644 --- a/src/skiplist_common.h +++ b/src/skiplist_common.h @@ -15,7 +15,7 @@ #include #include "common_define.h" -#define SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE 128 +#define SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE 64 typedef int (*skiplist_compare_func)(const void *p1, const void *p2); typedef void (*skiplist_free_func)(void *ptr); diff --git a/src/skiplist_set.c b/src/skiplist_set.c index 0684633..f1ff31c 100644 --- a/src/skiplist_set.c +++ b/src/skiplist_set.c @@ -203,8 +203,8 @@ int skiplist_set_insert(SkiplistSet *sl, void *data) return 0; } -static SkiplistSetNode *skiplist_set_get_previous(SkiplistSet *sl, void *data, - int *level_index) +static SkiplistSetNode *skiplist_set_get_equal_previous(SkiplistSet *sl, + void *data, int *level_index) { int i; int cmp; @@ -229,6 +229,56 @@ static SkiplistSetNode *skiplist_set_get_previous(SkiplistSet *sl, void *data, return NULL; } +static SkiplistSetNode *skiplist_set_get_first_larger_or_equal( + SkiplistSet *sl, void *data) +{ + int i; + int cmp; + SkiplistSetNode *previous; + + previous = sl->top; + for (i=sl->top_level_index; i>=0; i--) { + while (previous->links[i] != sl->tail) { + cmp = sl->compare_func(data, previous->links[i]->data); + if (cmp < 0) { + break; + } + else if (cmp == 0) { + return previous->links[i]; + } + + previous = previous->links[i]; + } + } + + return previous->links[0]; +} + +static SkiplistSetNode *skiplist_set_get_first_larger( + SkiplistSet *sl, void *data) +{ + int i; + int cmp; + SkiplistSetNode *previous; + + previous = sl->top; + for (i=sl->top_level_index; i>=0; i--) { + while (previous->links[i] != sl->tail) { + cmp = sl->compare_func(data, previous->links[i]->data); + if (cmp < 0) { + break; + } + else if (cmp == 0) { + return previous->links[i]->links[0]; + } + + previous = previous->links[i]; + } + } + + return previous->links[0]; +} + int skiplist_set_delete(SkiplistSet *sl, void *data) { int i; @@ -236,7 +286,7 @@ int skiplist_set_delete(SkiplistSet *sl, void *data) SkiplistSetNode *previous; SkiplistSetNode *deleted; - previous = skiplist_set_get_previous(sl, data, &level_index); + previous = skiplist_set_get_equal_previous(sl, data, &level_index); if (previous == NULL) { return ENOENT; } @@ -265,7 +315,7 @@ void *skiplist_set_find(SkiplistSet *sl, void *data) int level_index; SkiplistSetNode *previous; - previous = skiplist_set_get_previous(sl, data, &level_index); + previous = skiplist_set_get_equal_previous(sl, data, &level_index); return (previous != NULL) ? previous->links[level_index]->data : NULL; } @@ -274,7 +324,7 @@ int skiplist_set_find_all(SkiplistSet *sl, void *data, SkiplistSetIterator *iter int level_index; SkiplistSetNode *previous; - previous = skiplist_set_get_previous(sl, data, &level_index); + previous = skiplist_set_get_equal_previous(sl, data, &level_index); if (previous == NULL) { iterator->tail = sl->tail; iterator->current = sl->tail; @@ -285,3 +335,22 @@ int skiplist_set_find_all(SkiplistSet *sl, void *data, SkiplistSetIterator *iter iterator->tail = iterator->current->links[0]; return 0; } + +int skiplist_set_find_range(SkiplistSet *sl, void *start_data, void *end_data, + SkiplistSetIterator *iterator) +{ + if (sl->compare_func(start_data, end_data) > 0) { + iterator->current = sl->tail; + iterator->tail = sl->tail; + return EINVAL; + } + + iterator->current = skiplist_set_get_first_larger_or_equal(sl, start_data); + if (iterator->current == sl->tail) { + iterator->tail = sl->tail; + return ENOENT; + } + + iterator->tail = skiplist_set_get_first_larger(sl, end_data); + return iterator->current != iterator->tail ? 0 : ENOENT; +} diff --git a/src/skiplist_set.h b/src/skiplist_set.h index a77d859..a9470b1 100644 --- a/src/skiplist_set.h +++ b/src/skiplist_set.h @@ -59,11 +59,13 @@ int skiplist_set_insert(SkiplistSet *sl, void *data); int skiplist_set_delete(SkiplistSet *sl, void *data); void *skiplist_set_find(SkiplistSet *sl, void *data); int skiplist_set_find_all(SkiplistSet *sl, void *data, SkiplistSetIterator *iterator); +int skiplist_set_find_range(SkiplistSet *sl, void *start_data, void *end_data, + SkiplistSetIterator *iterator); static inline void skiplist_set_iterator(SkiplistSet *sl, SkiplistSetIterator *iterator) { - iterator->tail = sl->tail; iterator->current = sl->top->links[0]; + iterator->tail = sl->tail; } static inline void *skiplist_set_next(SkiplistSetIterator *iterator) diff --git a/src/tests/test_skiplist.c b/src/tests/test_skiplist.c index 94f0d98..e25187c 100644 --- a/src/tests/test_skiplist.c +++ b/src/tests/test_skiplist.c @@ -32,6 +32,29 @@ static int compare_func(const void *p1, const void *p2) return *((int *)p1) - *((int *)p2); } +void set_rand_numbers(const int multiple) +{ + int i; + int tmp; + int index1; + int index2; + + for (i=0; i #%d\n", record->key, record->line); + i++; + } + printf("count: %d\n\n", i); + /* if (skiplist_type == SKIPLIST_TYPE_FLAT) { flat_skiplist_print(&sl.u.flat, skiplist_tostring); @@ -272,12 +329,49 @@ static int test_stable_sort() return 0; } +static void test_find_range() +{ + int n_start; + int n_end; + int result; + int i; + int *value; + SkiplistIterator iterator; + + set_rand_numbers(2); + + for (i=0; i