Files
cKit/Sort/c_ShellSort.h
T

72 lines
1.9 KiB
C
Raw Normal View History

2026-08-29 01:58:00 +08:00
#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*/