Files
cKit/Sort/c_QuickSort.c
T
2026-08-29 01:58:00 +08:00

85 lines
2.9 KiB
C

#include <c_QuickSort.h>
/**
* Internal macro helper to swap two arbitrary blocks of memory of given size.
*/
C_STATIC_FORCE_INLINE
void c_SwapInternal(char* a, char* b, c_size_t size, void* temp) {
if (a == b) return;
memcpy(temp, a, size);
memcpy(a, b, size);
memcpy(b, temp, size);
}
/**
* Chooses the median of left, center, and right elements as the pivot,
* hides it at (right - 1), and returns a pointer to it.
*/
C_STATIC_FORCE_INLINE
void* c_MedianOfThree(char* arr, long long left, long long right, c_size_t size,
void* temp, int (*compar)(const void*, const void*)) {
long long center = left + (right - left) / 2;
// Order left, center, right
if (compar(arr + (left * size), arr + (center * size)) > 0) {
c_SwapInternal(arr + (left * size), arr + (center * size), size, temp);
}
if (compar(arr + (left * size), arr + (right * size)) > 0) {
c_SwapInternal(arr + (left * size), arr + (right * size), size, temp);
}
if (compar(arr + (center * size), arr + (right * size)) > 0) {
c_SwapInternal(arr + (center * size), arr + (right * size), size, temp);
}
// Place pivot at position (right - 1)
c_SwapInternal(arr + (center * size), arr + ((right - 1) * size), size, temp);
return arr + ((right - 1) * size);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
void c_QuickSortSub(char* arr, long long left, long long right, c_size_t size, void* temp,
int (*compar)(const void*, const void*)) {
// Optimization: Fallback to manual insertion sort for tiny arrays to prune deep recursion
if (left + 10 > right) {
// Basic Inline Insertion Sort boundary loop
for (long long i = left + 1; i <= right; i++) {
memcpy(temp, arr + (i * size), size);
long long j = i;
while (j > left && compar(arr + ((j - 1) * size), temp) > 0) {
memcpy(arr + (j * size), arr + ((j - 1) * size), size);
j--;
}
memcpy(arr + (j * size), temp, size);
}
return;
}
// Retrieve Median Pivot
c_MedianOfThree(arr, left, right, size, temp, compar);
long long i = left;
long long j = right - 1;
// Hoare Partitioning Loop
while (1) {
while (compar(arr + ((++i) * size), arr + ((right - 1) * size)) < 0);
while (compar(arr + ((--j) * size), arr + ((right - 1) * size)) > 0);
if (i < j) {
c_SwapInternal(arr + (i * size), arr + (j * size), size, temp);
} else {
break;
}
}
// Restore pivot to its correct final slot
c_SwapInternal(arr + (i * size), arr + ((right - 1) * size), size, temp);
// Recursively execute left and right segments
c_QuickSortSub(arr, left, i - 1, size, temp, compar);
c_QuickSortSub(arr, i + 1, right, size, temp, compar);
}