72 lines
1.9 KiB
C
72 lines
1.9 KiB
C
#ifndef INCLUDED_C_SHELLSORT_H
|
|||
|
|
#define INCLUDED_C_SHELLSORT_H
|
||
|
|
|
||
|
|
#ifndef INCLUDED_C_TYPES_H
|
||
|
|
#include <c_Types.h>
|
||
|
|
#endif /*INCLUDED_C_TYPES_H*/
|
||
|
|
|
||
|
|
#ifndef INCLUDED_C_MEMORY_H
|
||
|
|
#include <c_Memory.h>
|
||
|
|
#endif /*INCLUDED_C_MEMORY_H*/
|
||
|
|
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
void c_ShellSort(void* base, c_size_t num, c_size_t size,
|
||
|
|
int (*compar)(const void*, const void*)) {
|
||
|
|
if (base == NULL || num < 2 || size == 0) return;
|
||
|
|
|
||
|
|
char* arr = (char*)base;
|
||
|
|
|
||
|
|
// Stack optimization for memory swap space
|
||
|
|
#define STACK_LIMIT 128
|
||
|
|
char stack_buf[STACK_LIMIT];
|
||
|
|
void* temp = NULL;
|
||
|
|
|
||
|
|
if (size <= STACK_LIMIT) {
|
||
|
|
temp = stack_buf;
|
||
|
|
} else {
|
||
|
|
temp = C_ALLOC(size);
|
||
|
|
if (temp == NULL) return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Using Knuth's gap sequence: h = h * 3 + 1 (1, 4, 13, 40, 121, ...)
|
||
|
|
c_size_t gap = 1;
|
||
|
|
while (gap < num / 3) {
|
||
|
|
gap = gap * 3 + 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Start with the largest gap and work down to a gap of 1
|
||
|
|
while (gap > 0) {
|
||
|
|
for (c_size_t i = gap; i < num; i++) {
|
||
|
|
// temp = arr[i]
|
||
|
|
memcpy(temp, arr + (i * size), size);
|
||
|
|
|
||
|
|
c_size_t j = i;
|
||
|
|
|
||
|
|
// Shift elements of the gap-sorted variant until the correct position is found
|
||
|
|
// Loop guards prevent underflow on unsigned c_size_t subtraction (j >= gap)
|
||
|
|
while (j >= gap && compar(arr + ((j - gap) * size), temp) > 0) {
|
||
|
|
// arr[j] = arr[j - gap]
|
||
|
|
memcpy(arr + (j * size), arr + ((j - gap) * size), size);
|
||
|
|
j -= gap;
|
||
|
|
}
|
||
|
|
|
||
|
|
// arr[j] = temp
|
||
|
|
memcpy(arr + (j * size), temp, size);
|
||
|
|
}
|
||
|
|
// Reduce the gap
|
||
|
|
gap /= 3;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (size > STACK_LIMIT) {
|
||
|
|
C_FREE(temp);
|
||
|
|
}
|
||
|
|
#undef STACK_LIMIT
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#endif /*INCLUDED_C_SHELLSORT_H*/
|