# Erik Kastner 2008-02-13 iterative merge sort in ruby
require'rubygems'require'activesupport'# iterative merge sort. given [10,9,8,7,6,5,4,3,2,1], first loop would do
# [10,9] => [9,10], [8,7] => [7,8]... etc second loop
# [9,10,7,8] => [7,8,9,10]... etc
defmerge_sort(a)# a one element array is already sorted
return a unless a.size >1# first groups are like [[10], [9]]...
merge_size =2# loop until merge_size > array.size
# you can also find the nearst power of 2, for 10 thats 16
# that's (log(a.size) / log(2))**2
loopdo
offset =0
a.in_groups_of(merge_size)do |sub_array|
subs = sub_array.in_groups_of(merge_size /2)
sub_array.size.times do |i|nextif i+offset >= a.size
# after the sub elemnts are shifted off, sub arrays might be empty
# or have nil elements
if(subs[0].empty? || subs[0].first.nil?)
a[i+offset]= subs[1].shift;nextendif(subs[1].empty? || subs[1].first.nil?)
a[i+offset]= subs[0].shift;nextend# set a[i+offset] to the lesser of the first elements of the sub arrays
# shift that off the sub array
a[i+offset]=(subs[0].first < subs[1].first)? subs[0].shift : subs[1].shift
end
offset += sub_array.size
endbreakif merge_size > a.size
merge_size *=2end
a
end
a =[10,9,8,7,6,5,4,3,2,1]# a = (1..8).map{rand(200)}
puts "before: #{a.inspect}"
puts "after: "+ merge_sort(a).inspect