A few months ago I learned about the magic that allows radix sort to run in O(n)
time and space. Most tutorials on radix sort say it is useful for very large collections where the key values fall inside a defined range. They then go on to say that it's really only reasonable when sorting unsigned integers. The reasons made sense.
I also recently learned about the IEEE floating point specification and it got me thinking about about 2s-compliment signed ints at the same time. In both cases the MSB of the value represents the sign of the value, with 1 indicating a negative and 0 indicating positive. That means that an int or float with a MSB of 1 should go before another with a MSB of 0.
With that in mind, couldn't signed ints or floats be sorted with the following algorithm?
- Run Radix Sort using the raw bytes. This takes
O(n)
. Letp
be the count of positive numbers in the array. The array now has two parts.
array[0:p]
is a sorted array of the positive values.array[p:n]
is a reverse sorted array of the negative values.
- Initialize pointers
i = 0; j = n - 1
and the final return array of lengthn
. - While
msd(array[j])==1
, copyarray[j]
to the final array and decrementj
. This takesO(n-p)
- While
i < j
, copyarray[i]
to the final array and incrementi
. This takesO(p)
- The final array is now sorted.
If this works it runs in O(n) + O(n-p) + O(p) = O(n)
time. We can reuse the second array from the radix sort, which used O(n)
space.
This feels like a relatively easy way to extend Radix sort to signed values. Does it not work? What am I missing?