整列したい配列を a ( a[0] … a[n-1] ) とします。 もし n=1 ならば配列の要素は1個ですから、すでに整列されています。 n>1 の場合、てきとうな i に対して
したがって、配列 a の a[left] から a[right] まで を整列する関数を
def qsort(a, left, right) if left < right ある i に対して a[left] から a[i-1] までが ≦ a[i] a[i+1] から a[right] までが ≧ a[i] となるよう a を並べ替える(「a[i] を軸として分割」) qsort(a, left, i-1) qsort(a, i+1, right) end endと定義すれば qsort(a, 0, n-1) を実行することにより 配列 a 全体が整列されることとなります。
このような整列アルゴリズムをクイックソートといいます。 実用的には最速の整列法(たいていの場合は n log n に比例する程度の比較回数でよい)と考えられています。
require 'lib1' # おまじない def swap(a, i, j) # a[i] と a[j] を交換する t = a[i] a[i] = a[j] a[j] = t end def qsort(a, left, right) # クイックソートの本体 if left < right v = a[right] # この要素を left〜right の間の正しい位置へ移動 i = left-1 j = right while true # このループ内の条件は微妙なため単純に < を <= に # 変更したりすると動作が正しくなくなるので注意 i+=1; while a[i] < v do; i+=1; end j-=1; while a[j] > v do; j-=1; end if i >= j; break; end # while ループを終了 swap(a, i, j) end swap(a, i, right) # この時点で a[i] を軸として分割終了 qsort(a, left, i-1) qsort(a, i+1, right) end end def quick_sort(a) # 配列 a をクイックソート・アルゴリズムで整列する n = a.length qsort(a, 0, n-1) end n = 10 # いろいろ変更してみる array = sample_array(n) # ランダムに長さnの配列を生成 print_array(array) # n が大きいときはコメントアウトする quick_sort(array) print_array(array) # n が大きいときはコメントアウトする is_sorted(array) # この表示が OK とならなければ動作がおかしい
例 ---------------------------------------------------------------------- 0 1 2 3 4 5 6 7 8 (添字/インデックス) a = [66 77 56 66 74 44 90 89 58] qsort(a,0,8) 0 1 2 3 4 5 6 7 8 66 77 56 66 74 44 90 89 58 -> swap(a,0,5) -> swap(a,1,2) -> swap(a,2,8) 44 56 58 66 74 66 90 89 77 -> i=2 -> qsort(a,0,1) , qsort(a,3,8) qsort(a,0,1) 0 1 2 3 4 5 6 7 8 44 56 58 66 74 66 90 89 77 -> swap(a,1,1) 44 56 58 66 74 66 90 89 77 -> i=1 -> qsort(a,0,0), qsort(a,1,1) qsort(a,3,8) 0 1 2 3 4 5 6 7 8 44 56 58 66 74 66 90 89 77 -> swap(a,6,8) 44 56 58 66 74 66 77 89 90 -> i=6 -> qsort(a,3,5), qsort(a,7,8) qsort(a,3,5) 0 1 2 3 4 5 6 7 8 44 56 58 66 74 66 77 89 90 -> swap(a,3,5) 44 56 58 66 74 66 77 89 90 -> i=3 -> qsort(a,3,2), qsort(a,4,5) qsort(a,4,5) 0 1 2 3 4 5 6 7 8 44 56 58 66 74 66 77 89 90 -> swap(a,4,5) 44 56 58 66 66 74 77 89 90 -> i=4 -> qsort(a,4,3), qsort(a,5,5) qsort(a,7,8) 0 1 2 3 4 5 6 7 8 44 56 58 66 66 74 77 89 90 -> swap(a,8,8) 44 56 58 66 66 74 77 89 90 -> i=8 -> qsort(a,7,7), qsort(a,9,8) ----------------------------------------------------------------------
問35: 以下の配列をクイックソートプログラムで整列してみましょう。
問36: n を 50, 100, 500, 1000, 2000, 5000, 10000 と大きくしたとき のクイックソートプログラムの実行時間はどのようになるでしょうか。
時間計測の例:
require 'lib1' require 'sort' n = 10 a = sample_array(n) print_array(a) # insertion_sort(a) # どれか1つの # selection_sort(a) # コメントを # quick_sort(a) # 外して実行 print_array(a) is_sorted(a)
問37: 以下の配列を{選択整列・挿入整列・クイックソート} で整列してみましょう。
配布資料(PDF) を参照のこと。
私は非常勤のため、学内にはいません。したがって、質問などありましたらメール (nagoya@u-gakugei.ac.jp)でお願いします。