#include #include /** * 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; }