ふと、in-place で radix sort ができるか調べてみると、1bit 単位で quick sort みたいなことをすればできるようだ。
試しに書いてみた。
def inplace_radix_sort(ary)
max = 0
ary.each {|v|
unless v.is_a? Integer
raise ArgumentError, "non-integer element"
end
if v < 0
raise ArgumentError, "negative integer"
end
if max < v
max = v
end
}
inplace_radix_sort_internal(ary, 1 << (max.bit_length-1), 0, ary.length-1)
ary
end
def inplace_radix_sort_internal(ary, mask, i0, j0)
if mask == 0
return
end
i = i0
j = j0
while i <= j
if ary[i] & mask == 0
i += 1
elsif ary[j] & mask != 0
j -= 1
else
ary[i], ary[j] = ary[j], ary[i]
i += 1
j -= 1
end
end
# assert i == j+1
mask >>= 1
inplace_radix_sort_internal(ary, mask, i0, i-1)
inplace_radix_sort_internal(ary, mask, j+1, j0)
end
ary = (0...10).to_a.shuffle
p inplace_radix_sort(ary) #=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
再帰の深さは最大要素のビット数で、それぞれの深さにおいて結局は全ての要素を調べるので、O(n log max) か。
複数ビット単位でやるには、入れ替える前に要素の数を数えておけば可能なようだ。
[latest]