Add sorted list manipulation functions

This commit is contained in:
frsfnrrg 2018-07-15 10:27:18 -04:00
parent b314a8f2cc
commit 8f32069740
2 changed files with 69 additions and 0 deletions

View file

@ -147,3 +147,61 @@ void list_stable_sort(list_t *list, int compare(const void *a, const void *b)) {
list_inplace_sort(list, 0, list->length - 1, compare); list_inplace_sort(list, 0, list->length - 1, compare);
} }
} }
void list_sortedset_insert(list_t *list, void *item,
int compare(const void *item_left, const void *item_right),
void *replace(void *old_item, void* new_item)) {
if (list->length <= 0) {
list_add(list, item);
return;
}
size_t lower = 0;
size_t upper = (size_t)list->length - 1;
while (lower <= upper && upper != (size_t)-1) {
size_t div = (lower + upper) / 2;
int cv = compare(list->items[div], item);
if (cv < 0) {
lower = div + 1;
} else if (cv > 0) {
upper = div - 1;
} else {
list->items[div] = replace(list->items[div], item);
return;
}
}
list_insert(list, lower, item);
}
int list_sortedset_find(list_t *list,
int compare(const void *item, const void *cmp_to),
const void *cmp_to) {
if (list->length <= 0) {
return -1;
}
size_t lower = 0;
size_t upper = (size_t)list->length - 1;
while (lower <= upper && upper != (size_t)-1) {
size_t div = (lower + upper) / 2;
int cv = compare(list->items[div], cmp_to);
if (cv < 0) {
lower = div + 1;
} else if (cv > 0) {
upper = div - 1;
} else {
return div;
}
}
return -1;
}
int list_is_sortedset(list_t *list,
int compare(const void *left, const void *right)) {
for (size_t i = 1; i < (size_t)list->length; i++) {
if (compare(list->items[i - 1], list->items[i]) >= 0) {
return 0;
}
}
return 1;
}

View file

@ -12,6 +12,12 @@ void list_free(list_t *list);
void list_foreach(list_t *list, void (*callback)(void* item)); void list_foreach(list_t *list, void (*callback)(void* item));
void list_add(list_t *list, void *item); void list_add(list_t *list, void *item);
void list_insert(list_t *list, int index, void *item); void list_insert(list_t *list, int index, void *item);
// Insert an item into the list which is already sorted strictly ascending
// according to 'compare'. 'replace' is called when displacing an old item
// and returns the item which will take its place.
void list_sortedset_insert(list_t *list, void* item,
int compare(const void *item_left, const void *item_right),
void *replace(void *old_item, void* new_item));
void list_del(list_t *list, int index); void list_del(list_t *list, int index);
void list_cat(list_t *list, list_t *source); void list_cat(list_t *list, list_t *source);
// See qsort. Remember to use *_qsort functions as compare functions, // See qsort. Remember to use *_qsort functions as compare functions,
@ -20,6 +26,11 @@ void list_qsort(list_t *list, int compare(const void *left, const void *right));
// Return index for first item in list that returns 0 for given compare // Return index for first item in list that returns 0 for given compare
// function or -1 if none matches. // function or -1 if none matches.
int list_seq_find(list_t *list, int compare(const void *item, const void *cmp_to), const void *cmp_to); int list_seq_find(list_t *list, int compare(const void *item, const void *cmp_to), const void *cmp_to);
// Requires a list sorted strictly ascending according to 'compare';
// returns the index of the matching item, or -1 is no such item exists
int list_sortedset_find(list_t *list, int compare(const void *item, const void *cmp_to), const void *cmp_to);
// Check if a list is sorted strictly ascending according to compare
int list_is_sortedset(list_t *list, int compare(const void *left, const void *right));
// stable sort since qsort is not guaranteed to be stable // stable sort since qsort is not guaranteed to be stable
void list_stable_sort(list_t *list, int compare(const void *a, const void *b)); void list_stable_sort(list_t *list, int compare(const void *a, const void *b));
// swap two elements in a list // swap two elements in a list