Radix Sort implemented in C++
I think you're severely overcomplicating your solution. You can implement radix using the single array received in the input, with the buckets in each step represented by an array of indices that mark the starting index of each bucket in the input array.
In fact, you could even do it recursively:
// Sort 'size' number of integers starting at 'input' according to the 'digit'th digit
// For the parameter 'digit', 0 denotes the least significant digit and increases as significance does
void radixSort(int* input, int size, int digit)
{
if (size == 0)
return;
int[10] buckets; // assuming decimal numbers
// Sort the array in place while keeping track of bucket starting indices.
// If bucket[i] is meant to be empty (no numbers with i at the specified digit),
// then let bucket[i+1] = bucket[i]
for (int i = 0; i < 10; ++i)
{
radixSort(input + buckets[i], buckets[i+1] - buckets[i], digit+1);
}
}
Of course buckets[i+1] - buckets[i]
will cause a buffer overflow when i
is 9, but I omitted the extra check or readability's sake; I trust you know how to handle that.
With that, you just have to call radixSort(testcases, sizeof(testcases) / sizeof(testcases[0]), 0)
and your array should be sorted.
To speed up the process with better memory management, create a matrix for the counts that get converted into indices by making a single pass over the array. Allocate a second temp array the same size as the original array, and radix sort between the two arrays until the array is sorted. If an odd number of radix sort passes is performed, then the temp array will need to be copied back to the original array at the end.
To further speed up the process, use base 256 instead of base 10 for the radix sort. This only takes 1 scan pass to create the matrix and 4 radix sort passes to do the sort. Example code:
typedef unsigned int uint32_t;
uint32_t * RadixSort(uint32_t * a, size_t count)
{
size_t mIndex[4][256] = {0}; // count / index matrix
uint32_t * b = new uint32_t [COUNT]; // allocate temp array
size_t i,j,m,n;
uint32_t u;
for(i = 0; i < count; i++){ // generate histograms
u = a[i];
for(j = 0; j < 4; j++){
mIndex[j][(size_t)(u & 0xff)]++;
u >>= 8;
}
}
for(j = 0; j < 4; j++){ // convert to indices
m = 0;
for(i = 0; i < 256; i++){
n = mIndex[j][i];
mIndex[j][i] = m;
m += n;
}
}
for(j = 0; j < 4; j++){ // radix sort
for(i = 0; i < count; i++){ // sort by current lsb
u = a[i];
m = (size_t)(u>>(j<<3))&0xff;
b[mIndex[j][m]++] = u;
}
std::swap(a, b); // swap ptrs
}
delete[] b;
return(a);
}
Since your values are ints in the range of 0 ... 1,000,000
You can create a int array of of size 1,000,001, and do the whole thing in two passes
Init the second array to all zeros.
Make a pass through your input array, and use the value as a subscript to increment the value in the second array.
Once you do that then the second pass is easy. walk through the second array, and each element tells you how many times that number appeared in the original array. Use that information to repopulate your input array.