63 lines
2.3 KiB
C
63 lines
2.3 KiB
C
#include <c_LSDRadixSort.h>
|
|
#include <c_Memory.h>
|
|
|
|
/**
|
|
* Sorts an array of fixed-length strings stably using the LSD Radix Sort pipeline.
|
|
* Features upfront workspace allocations to completely eliminate heap thrashing in hot loops.
|
|
*
|
|
* Time Complexity: O(W * (N + R)) | Space Complexity: O(N + R) transient workspace memory
|
|
* @param sort Pointer to the initialized LSD config profile.
|
|
* @param arr Array of pointers to null-terminated char arrays (each must be at least W long).
|
|
* @param n Total number of strings inside the array.
|
|
*/
|
|
c_err_t c_LSDRadixSort_Sort(const c_LSDRadixSort_t* sort, char** arr, c_size_t n) {
|
|
if (sort == NULL || arr == NULL || sort->R == 0 || sort->W == 0) return C_ERR_PARAM;
|
|
if (n <= 1) return C_ERR_OK; // Trivial exit pass
|
|
|
|
c_size_t R = sort->R;
|
|
c_size_t W = sort->W;
|
|
|
|
// Upfront Transient Workspace Allocation: Eliminates allocation overhead in hot paths
|
|
char** aux = (char**)C_ALLOC(n * sizeof(char*));
|
|
c_size_t* count = (c_size_t*)C_ALLOC((R + 1) * sizeof(c_size_t));
|
|
|
|
if (aux == NULL || count == NULL) {
|
|
C_FREE(aux);
|
|
C_FREE(count);
|
|
return C_ERR_NOMEM;
|
|
}
|
|
|
|
// --- Core Iterative LSD Pass Loop ---
|
|
// Travel from right to left (Least Significant to Most Significant)
|
|
for (long long d = (long long)W - 1; d >= 0; d--) {
|
|
|
|
// Reset the counting frequency registers
|
|
memset(count, 0, (R + 1) * sizeof(c_size_t));
|
|
|
|
// Pass A: Compute frequency counts using character indices as bucket addresses
|
|
for (c_size_t i = 0; i < n; i++) {
|
|
unsigned char c = (unsigned char)arr[i][d];
|
|
count[c + 1]++;
|
|
}
|
|
|
|
// Pass B: Transform frequencies into structural start indexes (Prefix Sums)
|
|
for (c_size_t r = 0; r < R; r++) {
|
|
count[r + 1] += count[r];
|
|
}
|
|
|
|
// Pass C: Distribute strings to the temporary aux array (Guarantees Stable Order Sorting)
|
|
for (c_size_t i = 0; i < n; i++) {
|
|
unsigned char c = (unsigned char)arr[i][d];
|
|
aux[count[c]++] = arr[i];
|
|
}
|
|
|
|
// Pass D: Copy back copies natively to the primary tracking layout pointers
|
|
memcpy(arr, aux, n * sizeof(char*));
|
|
}
|
|
|
|
// Purge temporary scratchpad workspace containers cleanly
|
|
C_FREE(aux);
|
|
C_FREE(count);
|
|
return C_ERR_OK;
|
|
}
|