Web教材一覧アルゴリズム
(BOK大区分:1 基礎理論、中区分:2 アルゴリズムとプログラミング、中区分:2 アルゴリズム)

ソートの種類

学習のポイント

アルゴリズムの例として、また実際に利用される処理にソート(整列)があります。ここでは、ソートの代表的な方法を紹介します。個々の方法へのリンク元でもあります。

キーワード

アルゴリズム、選択整列法、バブルソート、シェルソート、順序づけ、計算量


ソート(整列)
ソート整列)とは、ある基準に従ってデータを並べ替えることです。ある項目の値の小さい順に並べることを昇順、大きい順に並べることを降順といいます。
 例えば、配列aを昇順にソートすると、次のようになります。
        a[1] a[2] a[3] a[4] a[5]
  ソート前  30 20 50 10 40
  ソート後  10 20 30 40 50
内部ソートと外部ソート
内部ソートとは、メモリ内にあるデータ、主に配列を対象にしたソートです。それに対して、磁気ディスクなど外部記憶装置にあるファイルのレコードを対象にしたソートを外部ソートといいます。
安定ソート
下表中の安定ソートとは、元の順序を維持したままソートできることです。
 例えば、売上ファイルのレコードに、日付、得意先コード、商品コードなどの項目があり、日付でソートされているとします。このファイルを得意先コードでソートしたとき、同じ得意先コードがあるとき、そのなかでは先の日付順にソートされていることです。
 安定ソートでない場合でも、得意先コードを第1順位、日付を第2順位に指定すればよいのですが、煩雑になります。安定ソートならば、そのような顧慮をする必要がありません。

基本的な内部ソート

バブルソート
分類:交換法、安定ソート
平均比較回数:n(n-1)/2
計算量:O(n2)
対象集合(配列など)の隣り合う要素を比較して、大小の順が逆であれば、それらの要素を入れ替えるという操作を繰り返して行う方法です。
昇順ソートのとき:A[i]>A[i+1] ならば、A[i] とA[i+1] をスワップ
降順ソートのとき:A[i]<A[i+1] ならば、A[i] とA[i+1] をスワップ
昇順のとき、小さい要素が泡(バブル)のように上(配列の先頭側)へ移動する
選択ソート
分類:選択法、安定ではない
平均比較回数:n(n-1)/2
計算量:O(n2)
対象集合から最も小さい(または最も大きい)要素を順次取り出して、端に置いていくことでソートする方法です。
昇順ソートならば、全体のなかで最小値(最大値)の要素を探し、その要素を先頭(末尾)に置きます。次に、対象になった要素以外での最小値(最大値)の要素をその次に置きます。これを繰り返すことにより、ソートができます。降順ソートの場合も同様です。
挿入ソート
分類:挿入法、安定ソート
計算量:O(n2)
特徴:データ移動回数が多い
対象集合の先頭付近がソートされているとして、対象集合の未ソートの部分から要素を順次取り出し,それまでに取り出した要素の集合に順序関係を保つよう挿入してソートを行う方法です。
A[1]~A[k]が既にソートされているとします。未ソートの最初の要素はX=A[k+1]です。XとA[1]~A[k]を比較して、入れるべき個所がiならば、A[i]~A[k]を一つ下にずらし(A[i+1]以降にコピーして、A[i]をXにすればよいのです。要素の移動数が非常に多くなります。

高速化を図った内部ソート

マージソート
分類:併合法、安定ソート
計算量:O(nlog2n)
特徴:大きな作業領域が必要
対象集合を単純に2等分した区分にします。それぞれの区分内でソートされていれば、2つの区分をマージ(併合)することにより、全体がソートされます。区分内でソートされていない場合は、それをさらに2等分して、同様な操作を行います。これを繰り返すことにより全体がソートされます。
マージソートは、クイックソートのように、状況によって速度が低下するようなことがありません。しかし、区分に分けるために、大きな作業領域が必要になります。
クイックソート
分類:交換法、安定ではない
平均比較回数:nlog2
(最悪の場合:n2
計算量:O(nlog2n)
全体のなかから、中間的な基準となる要素を1つ選び(ピボット-枢軸-という)、これより小さい要素と大きい要素の区分に分割します。さらに分割した2つの区分の中で分割を行います。これを繰り返してソートを行う方法です。
ピボットになる要素の選び方により、一方の区分に多くの要素が集まることがああり、その場合には効率が悪くなります。
シェルソート
分類:挿入法、安定ではない
計算量:O(nα)、α=1.2~1.5
ある間隔で要素を取り出した部分列を整列し、さらに間隔をつめた部分列を取り出してソートする方法です。
ある一定間隔おきに取り出した要素からなる部分列をそれぞれソートし(このときに挿入ソートや他の方法を用いることもあります)、更に間隔を詰めて同様の操作を行い、間隔が1になるまで繰り返すことによりソートが実現します。
この間隔の取り方、対象集合の事前の並びの状況により、処理効率は大きく変わり、計算量Oも厳密には与えられません。
ヒープソート
分類:選択法、安定ではない
計算量:O(nlog2n)
特徴:大きな作業領域が必要
未整列の部分を木構造の順序木(ヒープ構造)に構成し、そこから最大値又は最小値を取り出して既整列の部分に移す。この操作を繰り返して、実整列部分を縮めていく方法です。
ヒープ構造とは、2分木の各節点にデータを保持し、親のデータが2つの子のデータよりも小さく(大きく)なるように作られたデータ構造で、これにより、最小値(最大値)が根(ルート)になります。根のデータから、順にポインタにより取り出して、先頭(末尾)の要素とすることにより、昇順(降順)にソートできます。
部分的にヒープ構造にする(データとポインタ)ので、そのための作業領域が必要になります。

外部ソート

例えば、売上ファイルのレコードを得意先コード順や日付順でソートするというように、磁気ディスクなど外部記憶装置にあるデータをソートする方法です。直接編成ファイルや索引順編成ファイルのソートに関しては別途にして、ここでは順編成ファイルのソートについて考察します。
 レコードは、部分的には既にソートされている部分があります。それをといいます。連ごとに別のファイルに書き込めば、それらのファイル内ではソートされています。
 ソートされている複数のファイルから、ソートの順を維持しつつ一つのファイルにまとめることをマージ併合)といいます。(マージは配列の併合などにも用いられます)。連ごとに書き込まれているファイルをマージすることにより、ソートすることができます。
 書き込むファイルの個数に制約がある場合には工夫が必要です。外部ソート、マージに関しては、「マージ」(al-sort-merge)で説明します。

ソートに関連したアルゴリズム

順位づけ
前述のアルゴリズムは、配列aの要素を並べ替えるものでした。配列aはそのままにしておき、その順序を配列bに入れる操作です。これに関しては、「順序づけ」(al-sort-junjo)で説明します。
 なお、ある要素に、その次になる(前になる)要素の要素番号(添字の値)をポインタとして持つ方法に関しては、「リスト構造」(hs-data-list)を参照してください。
サーチ(探索)
与えた値xと同じ値をもつ配列aの要素を探す操作をサーチ探索)といいます。これに関しては、「サーチ」(al-search)で説明します。

アルゴリズムへ