Merge pull request #276 from szdytom/add-stable-sort

add stable_sort
This commit is contained in:
BLUELOVETH 2024-06-16 21:47:31 +08:00 committed by GitHub
commit 52abebfc16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 0 deletions

View File

@ -25,6 +25,18 @@ extern "C" {
*(out_index) = __first - (T*)(ptr); \ *(out_index) = __first - (T*)(ptr); \
} while(0) } while(0)
/**
* @brief Sorts an array of elements of the same type, using the given comparison function.
* @param ptr Pointer to the first element of the array.
* @param count Number of elements in the array.
* @param elem_size Size of each element in the array.
* @param cmp Comparison function that takes two elements and returns an integer similar to `strcmp`.
*/
void c11__stable_sort(void* ptr,
int count,
int elem_size,
int (*cmp)(const void* a, const void* b));
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,2 +1,47 @@
#include "pocketpy/common/algorithm.h" #include "pocketpy/common/algorithm.h"
#include <string.h>
#include <stdlib.h>
static void merge(char* a_begin,
char* a_end,
char* b_begin,
char* b_end,
char* res,
int elem_size,
int (*cmp)(const void* a, const void* b)) {
char *a = a_begin, *b = b_begin, *r = res;
while(a < a_end && b < b_end) {
if(cmp(a, b) <= 0) {
memcpy(r, a, elem_size);
a += elem_size;
} else {
memcpy(r, b, elem_size);
b += elem_size;
}
r += elem_size;
}
// one of the arrays is empty
for(; a < a_end; a += elem_size, r += elem_size)
memcpy(r, a, elem_size);
for(; b < b_end; b += elem_size, r += elem_size)
memcpy(r, b, elem_size);
}
void c11__stable_sort(void* ptr_,
int count,
int elem_size,
int (*cmp)(const void* a, const void* b)) {
// merge sort
char* ptr = ptr_, *tmp = malloc(count * elem_size);
for(int seg = 1; seg < count; seg *= 2) {
for(char* a = ptr; a < ptr + (count - seg) * elem_size; a += 2 * seg * elem_size) {
char* b = a + seg * elem_size, *a_end = b, *b_end = b + seg * elem_size;
if (b_end > ptr + count * elem_size)
b_end = ptr + count * elem_size;
merge(a, a_end, b, b_end, tmp, elem_size, cmp);
memcpy(a, tmp, b_end - a);
}
}
free(tmp);
}