msort.rb

30分シリーズ、その6。ネタ切れしたら、アルゴリズムの本を取り出せばいいことに気がついた。
ということで今回はマージソート

$ ruby msort.rb
オリジナル:[41, 26, 21, 26, 53, 93, 33, 11, 37, 25]
正順ソート:[11, 21, 25, 26, 26, 33, 37, 41, 53, 93]
逆順ソート:[93, 53, 41, 37, 33, 26, 26, 25, 21, 11]
def merge(lhs,rhs,&block)
  return rhs if lhs.empty?
  return lhs if rhs.empty?
 
  cmp = block ? block.call(lhs[0],rhs[0]) : (lhs[0] <=> rhs[0])
  if cmp <= 0
    [lhs[0]] + merge(lhs[1..-1],rhs,&block)
  else 
    [rhs[0]] + merge(lhs,rhs[1..-1],&block)
  end
end
 
def msort(items,&block)
  return items if items.size == 1
 
  before = items[0...items.size/2]
  after  = items[items.size/2..-1]
 
  merge msort(before,&block),msort(after,&block),&block
end

# テストデータ生成
array = (1..10).map{
  rand(100)
}

# 表示
puts "オリジナル:#{array.inspect}"
puts "正順ソート:#{msort(array).inspect}"
puts "逆順ソート:#{msort(array){|a,b| b <=> a }.inspect}"

配列をリストとして扱おうとして、ところどころに無理がでてる。というか、標準ライブラリにリスト入れてくれないかな。