Files
cKit/Sort/c_HeapSort.h
T
2026-08-29 01:58:00 +08:00

104 lines
3.0 KiB
C

#ifndef INCLUDED_C_HEAPSORT_H
#define INCLUDED_C_HEAPSORT_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*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
/**
* 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);
}
/**
* Standard Sift-Down structural loop modified to build/maintain a Max-Heap.
*/
C_STATIC_FORCE_INLINE
void c_Heapify(char* arr, c_size_t num, c_size_t root, c_size_t size,
void* temp, int (*compar)(const void*, const void*)) {
c_int_t current = root;
while (1) {
c_int_t left_child = (2 * current) + 1;
c_int_t right_child = (2 * current) + 2;
c_int_t largest = current;
if (left_child < num &&
compar(arr + (left_child * size), arr + (largest * size)) > 0) {
largest = left_child;
}
if (right_child < num &&
compar(arr + (right_child * size), arr + (largest * size)) > 0) {
largest = right_child;
}
if (largest == current) {
break;
}
c_SwapInternal(arr + (current * size), arr + (largest * size), size, temp);
current = largest;
}
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
/**
* Top-Level Framework Entry Point for Heapsort.
* Time Complexity: O(n log n) | Space Complexity: O(1) in-place | Stable: No
*/
C_STATIC_FORCE_INLINE
void c_HeapSort(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;
#define HEAP_STACK_LIMIT 128
char stack_buf[HEAP_STACK_LIMIT];
void* temp = (size <= HEAP_STACK_LIMIT) ? stack_buf : C_ALLOC(size);
if (temp == NULL) return;
// Safely cast size parameters to signed c_int_t variables before starting the algorithm loops
c_int_t total_items = (c_int_t)num;
// Phase 1: Build the Max-Heap from the bottom up (Floyd's heap construction)
for (c_int_t i = (total_items / 2) - 1; i >= 0; i--) {
c_Heapify(arr, total_items, i, size, temp, compar);
}
// Phase 2: In-place sorted array extraction
for (c_int_t k = total_items - 1; k > 0; k--) {
// Swap root max element to current end positions
c_SwapInternal(arr, arr + (k * size), size, temp);
// Re-heapify the remaining sub-heap structure
c_Heapify(arr, k, 0, size, temp, compar);
}
if (size > HEAP_STACK_LIMIT) {
C_FREE(temp);
}
#undef HEAP_STACK_LIMIT
}
#endif /*INCLUDED_C_HEAPSORT_H*/