定番アルゴリズムを
徹底理解!

@teapipin
ソートの分類
 O(n2)であるソート
  挿入ソート     “実世界っぽい”
   • (改良版)シェルソート
  選択ソート “プログラムっぽい”
  バブルソート “いかにもアルゴリズムっぽい”

 O(nlog(n))であるソート
  クイックソート
  マージソート
  ヒープソート
挿入ソート
 未ソートのデータを1つひとつソート済みの
 列の適切な位置に差し込んでいく方法

繰り返し回数がデータ個数の2乗に比例する
       O(n2) と表現
 ソートの対象にするデータの個数が
 増えすぎると、計算量(繰り返し回数)が
 爆発的に増えてしまう
シェルソート(改良挿入ソート)
 挿入ソートの改良版
 単純な挿入ソートをする前に一定間隔で
 取り出したデータについて挿入ソートを行う

       繰り返し回数 O(n1.25)
 一般的に間隔の変化は数列 ak+1 = 3 ak+1 で
 作られる1, 4, 13, 40, 121...をデータの個数に
 応じて大きなものから使っていく
選択ソート
 データの中から一番小さいデータを見つけては
 取り出して最後の一個まで並べる方法
 配列の添え字だけを覚えておいて、
 最後にデータを入れ替える

     繰り返し回数 O(n2)

 データの個数が十分少ないと分かっている場合
 以外はほとんど使われない
バブルソート
 隣り合った2つのデータを比較して
 小さいものが先に来るように並べ替える
 データの入れ替えを何度も実行するため、
 挿入ソートと比べると効率が悪い
     繰り返し回数 O(n2)

 改良版として「シェーカーソート」や
 「コームソート(櫛ソート)」がある
O(n2)であるソートの実行結果
  Perlを用い、5000の数字データを並べ替え、
  消費時間を求めた(単位:CPU秒)
         正順      ランダム    逆順          特徴
挿入ソート     0.03    8.73   17.00   ソート済みは早いが
                                 極端に遅くなっていく
選択ソート     9.89   10.11   10.52   ほとんど変化なし

バブルソート   25.64   32.83   38.41   ソート済みでも時間が
                                 かかる

 •正順とはソート済みのデータ、逆順とは全てを並べ替える必要のあるデータ
 •ランダムとは、5000個の数値(負の数を含む)をランダムに2種類発生させ、
 それぞれについて3回試行を行い、合計6回の平均値を求めた
ヒープソート (1)
  処理の手間がやや複雑なため一般にはク
  イックソートのほうが遅い
  特定の並びに対して極端に遅くなるという
  ことはないため「安定した」アルゴリズムで
  ある
  ヒープ(heap) 二分木構造であるノードの
  値はその子ノードの値より大きい、という関
  係を持つ
 安定ソートとは、同等なデータのソート前の順序が、ソート後も保存されるもの
 つまり、ソート途中の各状態において、常に順位の位置関係を保っていること
ヒープソート (2)
 ヒープは配列で容易に表現できる
 あるノードの子ノードの添え字は、
  (そのノードの添え字+1)×2
  そこから1ひいたもの
 親ノードの添え字は、
  自分の添え字から1をひき、余りを考えずに
  2で割った商
ヒープソート (3)
 まず配列の最後尾に当たるノードをヒープ
 から除外して、ここにルート・ノードの値を
 格納
 それまでその最後尾のノードにあった値は
 ピープの根に移し、再び親子関係が正しく
 なるようにヒープを再構築する
 これを順次繰り返していく

定番アルゴリズムを徹底理解!