質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

Q&A

解決済

1回答

2282閲覧

ruby にてマージソートのアルゴリズムを書いています。どうも詰めが甘いようです。

shocyu

総合スコア17

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

0グッド

0クリップ

投稿2015/10/07 10:04

ruby で使えるアルゴリズムのライブラリを製作すべく、マージソートのアルゴリズムを書いてみました。

エラーは修復されたのですが、どうも詰めが甘いようで、正しい結果が出力されません。余計な処理が入っているかと思われます。

ソースは以下になります。もし不要な処理や足りない部分がありましたらご指摘お願いします。

ruby

1# Sort モジュール(クイックソートとマージソートの処理で構成) 2module Sort 3 4#merge_sort メソッド(マージソート) 5#引数 (n, x) = (配列の要素の数、ソートする配列) 6def self.merge_sort(n, x) 7 8 i, j, k, m = 0, 0, 0, 0 9 10 if n <= 1 11 return 12 end 13 14 m = n / 2 15 16 buffer = x[m..(n - 1)] 17 18 # ブロックを前半と後半に分けてソート(再帰呼び出し) 19 merge_sort(m, x) 20 merge_sort(n - m, buffer) 21 22 # x の前半を x の後半にコピー 23 x[(n - m)..(n - 1)] = x[0..(m - 1)] 24 25 j = n - m 26 27 # buffer(ブロックの後半をソートした配列)とxの後半とで比較して、小さい方をxの前半に入れる 28 while i < m && j < n do 29 if buffer[i] <= x[j] 30 x[k] = buffer[i] 31 k += 1 32 i += 1 33 else 34 x[k] = x[j] 35 k += 1 36 j += 1 37 end 38 end 39 40 while i < m do 41 x[k] = buffer [i] 42 k += 1 43 i += 1 44 end 45 46 #p x 47 48end 49# merge_sort メソッド終わり 50 51end 52#Sort モジュール終わり 53 54#配列を生成し、ソートする(main 処理) 55 56#配列の大きさを入力 57puts "Number of index" 58a = gets.to_i 59N = a 60 61# 要素数Nの配列を生成 62sort_array = Array.new(N) 63 64puts "Before sort" 65# 1000以下の乱数を生成し、sort_array配列に格納 66for i in 0..(N - 1) do 67 68 sort_array[i] = Random.rand(1000) 69 print sort_array[i].to_s + ", " 70end 71 72puts "\n" 73 74puts "Sort is started" 75# quick_sort メソッド呼び出し 76Sort.merge_sort(N, sort_array) 77 78puts "Sort ended" 79for i in 0..(N - 1) do 80 print sort_array[i].to_s + ", " 81end 82 83puts "\n"

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

間違いの指摘だけでは質問者さんの「ため」にならないので、敢えて遠回しに説明します。

配列[3,1,2]を渡したときの挙動を追ってみてください。
前半、後半のソート後、最初のループに入る前の変数の状態は
x = 3,1,3
buffer = 1,2
i,j,k,m,n=0,2,0,1,3
ですね。ループを1回実行すると、
x = 1, 1, 3
buffer = 1, 2
i,j,k,m,n=1,2,1,1,3
ですね。再度、条件をチェックすると、満たしませんね。
次のループも見てみましょう。これも条件を満たさないですね。

…あれあれ、関数が終わってしまいました。
bufferの一部分のコピーが終わっていませんね。
よく考えてみましょう。bufferの長さっていくつでしたっけ?
そうです、n-mです。mではありません。
配列の長さが奇数のときに、挙動がおかしくなっていたのですね。

…長ったらしく机上デバッグしましたが、要はそういうことです。

投稿2015/10/08 04:12

majiponi

総合スコア1720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shocyu

2015/10/09 02:36

majiponi さん、丁寧な解説ありがとうございます。返信遅れてすみません。修正して実行してからお返事したいと思い、今となりました。 マージソートにおいては、配列の長さが奇数の時が問題、ということを押さえて、最もシンプルな例を用いて間違いを検出する、という方法が必要だったことに気付かされました。 次に同じような不具合が生じた場合には、ここでご指摘いただいた形でデバッグが出来るようにしてまいります。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問