資格道場 › レッスン一覧 › アルゴリズムとプログラミング
アルゴリズムとプログラミング・12/13・13分

整列(ソート)アルゴリズムの比較

ゴール

バブル・選択・挿入・クイック・マージ・ヒープ・シェル・基数の8つの整列法を説明文から見分け、バブルソートの交換の順番、選択ソートの比較回数、シェルソートと基数ソートの手順を自力で追えるようになる。

整列は「説明文を読んでどの方法か当てる」問題が毎回のように出ます。特にクイックソートは本試験でも繰り返し出題されています。手順を追う問題も、動きを一度つかめば確実に取れる得点源です。

このレッスンで稽古する(用語チェック・過去問)

まず全体像:8つの整列法を一言で

整列(ソート)は、データを小さい順(昇順)か大きい順(降順)に並べ替える処理です。試験に出るのは、整列法の説明文を読んで名前を当てる問題がほとんどです。下の表の「一言でいうと」を言えるようにすれば、名前当ての問題は解けます。

整列法 一言でいうと 説明文に出るキーワード
バブルソート 隣どうしを比べ、順番が逆なら入れ替える 「隣り合う要素を比較」「逆順なら交換」
選択ソート 残りから最小値(最大値)を探し、先頭に置く 「最小値を求め、それを除いた部分からまた最小値を求める」
挿入ソート 整列済みの列の正しい位置に、1つずつ差し込む 「整列済みのデータ列の正しい位置に追加」
クイックソート 基準値より小さいグループと大きいグループに分け、それぞれで繰り返す 「基準値」「大きいグループと小さいグループに分割」「再帰的」
マージソート 細かく分けてから、整列しながら合体(併合)させる 「併合」「マージ」
ヒープソート 未整列部分をヒープ(順序木)にし、根から最大値(最小値)を取り出して整列済みに移す 「順序木」「最小値を取り出して整列済みに移す」
シェルソート 一定の間隔おきの要素で整列し、間隔を詰めながら繰り返す 「ある間隔おきに取り出した要素」「間隔が1になるまで」
基数ソート 1の位、10の位…と桁ごとにグループ分けして並べ直す 「1の位の値で0〜9のグループに分ける」

ヒープソートは前のレッスンで学んだヒープを使います。ヒープは「親が子より必ず大きい(小さい)」木なので、根を取ればいつでも最大値(最小値)が手に入ります。

クイックソート:最頻出。「基準値で2つに分ける」

クイックソートは、ピボット(基準値)を1つ選び、それより小さい値のグループと大きい値のグループに分けます。分けた各グループの中でもまたピボットを選び、同じ分割を繰り返します。このように、同じ手順を小さい範囲に当てはめて繰り返すことを再帰といいます。

たとえるなら、クラスを「160cm未満」と「160cm以上」の2組に分け、それぞれの組をまた基準を決めて半分に分けていくやり方です。最後は1人ずつになり、全員が身長順に並びます。

flowchart TD
  A["5, 3, 8, 1, 9, 2(基準値 5)"] --> B["5より小さい: 3, 1, 2"]
  A --> C["5"]
  A --> D["5より大きい: 8, 9"]
  B --> E["さらに基準値を選んで分割 → 1, 2, 3"]
  D --> F["さらに分割 → 8, 9"]
  • 平均すると速い整列法です(計算量は n log n に比例。計算量とは、データ数 n が増えたとき手間がどれだけ増えるかの目安)。
  • 基準値が毎回端の値になると、分割が偏って遅くなります(最悪は n² に比例)。そのため、前半と後半が同じくらいの大きさになる基準値を選ぶのが望ましいとされます。

マージソートとの見分け方:クイックソートは「先に大小で分ける」方法で、合体の操作はありません。マージソートは「とにかく半分に分け、整列しながら併合する」方法です。説明文に「併合」とあればマージソート、「基準値」とあればクイックソートです。

クイックソート:先に大小で分ける5, 3, 8, 1, 9, 23, 1, 258, 95より小さい基準値5より大きい合体の操作はないマージソート:分けてから併合する5, 3, 8, 1, 9, 25, 3, 81, 9, 2それぞれ整列3, 5, 81, 2, 9併合1, 2, 3, 5, 8, 9
同じ6個のデータでの比較。クイックソートは基準値5で先に大小に分けるだけで合体はしない。マージソートは半分に分け、それぞれ整列してから併合する。

バブルソート:隣どうしの比較と交換

バブルソートは、隣り合う2つを比べて、順番が逆なら入れ替えます。これを端から端まで1回行うことを1パスと呼びます。泡(バブル)が水面に浮かぶように、値が1つずつ端へ運ばれるのが名前の由来です。

1パス後に何が決まるかは、走査の向きで決まります。

走査の向き 小さい順に並べるとき、1パス後に確定するもの
先頭 → 末尾 最大値が末尾 A[n] に来る
末尾 → 先頭 最小値が先頭 A[1] に来る

大きい値は交換のたびに後ろへ運ばれるので、先頭から走査すると最大値が末尾まで運ばれます。逆に末尾から走査すると、小さい値が前へ運ばれて最小値が A[1] に来ます。擬似コード(プログラムを日本語風に書いたもの)の問題では、内側ループの変数が n から減っていくか、増えていくかをまず確認しましょう。

先頭→末尾へ1パス(小さい順)最初5381925と3 交換3581925と8 そのまま3581928と1 交換3518928と9 そのまま3518929と2 交換3518291パス後351829最大値 9 が末尾 A[n] に確定
先頭から末尾へ1パス走査する様子。比べる2つ(色付き)が1つずつ右へずれ、大きい値が後ろへ運ばれて、最大値9が末尾に確定する。

選択ソート:比較回数は n(n−1)/2

選択ソートは、未整列部分から最小値(大きい順なら最大値)を探し、未整列部分の先頭と交換します。これを繰り返すと、先頭から順に確定していきます。

比較回数は、データの並び方に関係なく次のとおりです。

  • 1回目:残り n 個から探すので n−1 回比較
  • 2回目:n−2 回 … 最後は 1 回
  • 合計:(n−1)+(n−2)+…+1 = n(n−1)/2

例:n=5 なら 4+3+2+1 = 10 で、5×4÷2 = 10 と一致します。迷ったら n=2 や n=3 を代入して確かめると確実です(n=3 なら比較は2回+1回=3回で、3×2÷2 = 3)。

選択ソート n=5 の比較回数1回目:4回確定2回目:3回確定確定3回目:2回確定確定確定4回目:1回合計 10回4+3+2+1 = 5×4÷2 = 10
n=5 の選択ソート。1回終わるごとに先頭が1つ確定し、残りが1つ減るので、比較回数は4回、3回、2回、1回と減って合計10回になる。

シェルソートと基数ソート:手順を追う問題

シェルソートは、挿入ソートの改良版です。まず離れた間隔 H ごとの部分列を挿入法で整列し、H を小さくしながら繰り返し、最後は H=1(ふつうの挿入ソート)で仕上げます。遠くの要素を先に大まかに動かしておくので、最後の挿入ソートの手間が少なくて済みます。

基数ソートは、大小の比較をしません。代わりに、1の位の数字で0〜9のグループに分けて並べ直し、次に10の位で同じことをする、と下の桁から順に処理します。グループの中では前の順番を崩さないのがルールで、これがあるから最後の桁まで処理すると全体が整列します。

どちらの問題も、問われているのは「途中でどうなるか」です。最後まで整列が終わった答え(きれいに並んだ選択肢)に飛びつかず、問題が指定した手順のところで止めましょう。

基数ソート:下の桁から順に分ける最初25132115▼ 1の位で分ける1の位が1211の位が3131の位が525, 15並べ直し21132515▼ 10の位で分ける10の位が113, 1510の位が221, 25完成13152125グループ内は前の順番を崩さない
基数ソートの例。1の位、10の位の順にグループ分けして並べ直す。グループ内では前の順番を崩さないので、最後には全体が整列する。
例題 1

バブルソートで2回目に交換されるデータ

データ列 2, 7, 3, 5, 6, 8, 4, 1 に対して先頭からバブルソートを行い,小さい順に並べ替える。2 回目に交換が行われるデータはどれか。

ア 3 と 7
イ 4 と 5
ウ 4 と 7
エ 5 と 7

出典:基本情報技術者試験 科目A免除 修了試験 20260726 実施分 問6

解き方と答えを見る
  1. データ列は 2, 7, 3, 5, 6, 8, 4, 1。先頭から隣どうしを比べ、左の方が大きければ交換する。
  2. 2 と 7 を比べる:2 < 7 なので交換しない。
  3. 7 と 3 を比べる:7 > 3 なので交換(1回目)。列は 2, 3, 7, 5, 6, 8, 4, 1 になる。
  4. 7 と 5 を比べる:7 > 5 なので交換(2回目)。列は 2, 3, 5, 7, 6, 8, 4, 1 になる。
  5. 2回目に交換されたのは 5 と 7。

答え:エ(5 と 7)。3 と 7 の交換は1回目なので、アは誤り。

例題 2

末尾から走査するバブルソートの1パス後

配列A[i](i=1,2,…,n)を,次のアルゴリズムによって整列する。行2〜3の処理が初めて終了したとき,必ず実現されている配列の状態はどれか。 〔アルゴリズム〕 行番号 1 iを1からn-1まで1ずつ増やしながら行2〜3を繰り返す 2 jをnからi+1まで1ずつ減らしながら行3を繰り返す 3 もしA[j]<A[j-1]ならば,A[j]とA[j-1]を交換する

ア A[1]が最小値になる。
イ A[1]が最大値になる。
ウ A[n]が最小値になる。
エ A[n]が最大値になる。

出典:基本情報技術者試験 科目A免除 修了試験 20220612 実施分 問9

解き方と答えを見る
  1. 外側ループ i=1 のとき、内側ループの j は n から i+1=2 まで、1ずつ減っていく。
  2. j=n のときは A[n] と A[n−1]、次は A[n−1] と A[n−2]…と、末尾から先頭に向かって比べる。
  3. A[j] < A[j−1] のときに交換するので、小さい値ほど前へ運ばれる。
  4. 最小値は、どこにあっても交換を重ねて前へ運ばれ、j=2 の比較で A[1] に入る。
  5. したがって、行2〜3が初めて終わったとき、A[1] は必ず最小値になっている。

答え:ア(A[1] が最小値になる)

例題 3

選択ソートの比較(α印)の実行回数

流れ図に従って,選択ソートによって値を大きい順に整列するとき,α印の処理(比較)が実行される回数を表す式はどれか。
流れ図(上から順): 開始 → ループ始端「交換 i:1,1,n-1」 → 処理「i→k」 → ループ始端「最大値 j:i+1,1,n」 → 判定「x(j):x(k)」(α印の矢印がこの判定を指す)。「≦」の場合はループ端「最大値」へ戻る。「>」の場合は 処理「j→k」を経てループ端へ。 → ループ終端「最大値」 → 処理「x(k)→w,x(i)→x(k),w→x(i)」 → ループ終端「交換」 → 終了 (注) ループ端の繰返し指定は,変数名:初期値,増分,終値を示す。

ア n(n-1)/2
イ n(n-1)
ウ n(n+1)/2
エ n(n+1)

出典:基本情報技術者試験 科目A免除 修了試験 20110626 実施分 問7

解き方と答えを見る
  1. 外側ループ「交換」は、i が 1 から n−1 まで回る。
  2. 内側ループ「最大値」は、j が i+1 から n まで回る。1回まわるごとに α の比較が1回行われるので、比較回数は n−i 回。
  3. i=1 のとき n−1 回、i=2 のとき n−2 回、…、i=n−1 のとき 1 回。
  4. 合計は (n−1)+(n−2)+…+1 = n(n−1)/2。
  5. 確認:n=3 のとき 2+1 = 3 回。式に代入すると 3×2÷2 = 3 で一致する。

答え:ア(n(n−1)/2)

例題 4

シェルソートで手順(3)を実行する回数

次の手順はシェルソートによる整列を示している。データ列 7,2,8,3,1,9,4,5,6 を手順 (1)~(4) に従って整列するとき,手順 (3) を何回繰り返して完了するか。ここで,[ ] は小数点以下を切り捨てた結果を表す。 〔手順〕 (1) [データ数÷3] → H とする。 (2) データ列を互いに H 要素分だけ離れた要素の集まりからなる部分列とし,それぞれの部分列を,挿入法を用いて整列する。 (3) [H÷3] → H とする。 (4) H が 0 であればデータ列の整列は完了し,0 でなければ (2) に戻る。

ア 2
イ 3
ウ 4
エ 5

出典:基本情報技術者試験 科目A免除 修了試験 200907 実施分 問5

解き方と答えを見る
  1. データ数は 9。手順(1)で H = [9÷3] = 3 とする。
  2. 手順(2)で、間隔3の部分列をそれぞれ挿入法で整列する。
  3. 手順(3)で H = [3÷3] = 1 とする(1回目)。
  4. 手順(4)で H は 0 ではないので、(2)に戻る。H=1 で全体を挿入法で整列する。
  5. 手順(3)で H = [1÷3] = 0 とする(2回目)。
  6. 手順(4)で H が 0 になったので完了。手順(3)の実行は合計2回。

答え:ア(2回)。H=1 で整列した後にも(3)を1回実行することを数え忘れないこと。

例題 5

基数ソートで10の位まで処理した結果

6 個の数値 180,315,282,410,645,525 を並べ替える。手順 1~4 は途中までの手順を示したものである。手順 4 まで終わったときの結果はどれか。 手順 1 並びの左側から順に,数値の 1 の位の値によって 0~9 のグループに分ける。 手順 2 次に 0 のグループの数値を左側から順に取り出して並べ,その右側に 1 のグループ,以下順に 2~9 のグループの数値を並べていく。 手順 3 手順 2 で得られた数値の並びの左側から順に,数値の 10 の位によって 0~9 のグループに分ける。 手順 4 手順 2 と同様に,0 のグループの数値から順に並べる。 ここで,グループ内では,処理が行われた数値を左側から順に並べるものとする。

ア 180,282,315,410,525,645
イ 315,410,525,180,282,645
ウ 410,315,525,645,180,282
エ 645,525,410,315,282,180

出典:基本情報技術者試験 科目A免除 修了試験 200912 実施分 問7

解き方と答えを見る
  1. 元の並びは 180, 315, 282, 410, 645, 525。
  2. 手順1:1の位でグループに分ける。0のグループは 180, 410、2のグループは 282、5のグループは 315, 645, 525(グループ内は元の順を保つ)。
  3. 手順2:0→2→5 の順に並べると 180, 410, 282, 315, 645, 525。
  4. 手順3:この並びを10の位で分ける。1のグループは 410, 315、2のグループは 525、4のグループは 645、8のグループは 180, 282。
  5. 手順4:1→2→4→8 の順に並べると 410, 315, 525, 645, 180, 282。

答え:ウ(410,315,525,645,180,282)。100の位はまだ処理していないので、全体は整列しきっていない。

要点(試験直前に読む)

  • 説明文のキーワードで見分ける:隣り合う比較交換=バブル、最小値を選ぶ=選択、正しい位置に挿入=挿入、基準値で大小に分割=クイック、併合=マージ、順序木=ヒープ、間隔おき=シェル、桁ごとにグループ分け=基数。
  • クイックソートは「基準値で小さいグループと大きいグループに分け、再帰的に繰り返す」。前半と後半が同じくらいの大きさになる基準値を選ぶのが望ましい。
  • バブルソートで1パス後に確定するのは端の値。先頭から走査すると最大値が末尾に、末尾から走査すると最小値が先頭に来る。
  • 選択ソートの比較回数は (n−1)+(n−2)+…+1 = n(n−1)/2。迷ったら n=3 を代入して確かめる。
  • シェルソートと基数ソートの手順問題は、問題が指定したところで止めて答える。

ひっかけ

  • 説明文の名前当ての問題では、残りの3つの選択肢に別の整列法の説明が並ぶ。表のキーワードと一つずつ照らし合わせれば消去できる。
  • バブルソートの1パス後の問題は、走査の向きを逆に読ませるのが狙い。内側ループの変数が n から減るなら、最小値が A[1] に来る。
  • 「何回目の交換」を問う問題は、交換しなかった比較を数えてしまうとずれる。交換が起きたときだけ数える。
  • 選択ソートの比較回数で n(n+1)/2 や n(n−1) を選ばせる。ループの範囲(i は n−1 まで、j は i+1 から)を確認し、小さな n を代入して検算する。
  • シェルソートでは、H=1 で整列した後の H=0 にする手順(3)を数え忘れやすい。基数ソートでは、整列済みに見える選択肢に飛びつかないこと。10の位までしか処理していなければ、100の位はばらばらのまま。

用語(13)

整列(ソート) せいれつ(sort)
データを決まった順序(昇順・降順)に並べ替える処理。
⚠ 探索(データの中から目的の値を探す処理)とは別のもの。2分探索などは整列済みのデータを前提にする。
バブルソート ばぶるそーと(bubble sort)
隣り合う2つの要素を比べ、順番が逆なら交換する操作を繰り返す整列法。
⚠ 選択ソートは「最小値を探して先頭と交換」で、交換する相手が隣とは限らない。「隣り合う」とあればバブルソート。
パス ぱす(pass)
整列の途中で、データ列を端から端まで1回走査すること。
選択ソート せんたくそーと(selection sort)
未整列部分から最小値(最大値)を選び、未整列部分の先頭と交換することを繰り返す整列法。
⚠ 挿入ソートは「整列済みの列に1つずつ差し込む」。選択ソートは「残りから最小値を探す」。
挿入ソート そうにゅうそーと(insertion sort)
整列済みの列の正しい位置に、未整列の要素を1つずつ差し込んでいく整列法。
⚠ 選択ソートと混同しやすい。キーワードは「正しい位置に挿入(追加)」。
クイックソート くいっくそーと(quick sort)
基準値より小さいグループと大きいグループに分け、各グループで同じ分割を再帰的に繰り返す整列法。
⚠ マージソートも分割するが、整列しながら「併合」する。説明文に基準値があればクイックソート、併合があればマージソート。
ピボット(基準値) ぴぼっと(pivot)
クイックソートで、グループを大小に分けるときの境目として選ぶ値。
再帰 さいき
ある処理の中で、より小さな範囲に対して同じ処理を呼び出して繰り返すこと。
マージソート まーじそーと(merge sort)
データを細かく分けてから、整列しながら合体(併合)させていく整列法。
⚠ クイックソートとの見分け方は「併合」の有無。
ヒープソート ひーぷそーと(heap sort)
未整列部分をヒープ(順序木)にし、根から最大値(最小値)を取り出して整列済みに移すことを繰り返す整列法。
⚠ 選択ソートも最小値を取り出すが、最小値を探す手段が違う。「順序木」「ヒープ」とあればヒープソート。
シェルソート しぇるそーと(shell sort)
一定の間隔ごとの要素で部分列を作って挿入法で整列し、間隔を詰めながら最後は間隔1で仕上げる整列法。
⚠ 「ある間隔おきに取り出した要素」とあればシェルソート。基数ソートの「桁ごと」と混同しない。
基数ソート きすうそーと(radix sort)
下の桁から順に、桁の数字でグループに分けて並べ直すことを繰り返す整列法。大小の比較はしない。
⚠ 「1の位で0〜9に分ける」とあれば基数ソート。途中の桁までしか処理しなければ、まだ整列は終わっていない。
計算量 けいさんりょう
データ数 n が増えたとき、処理の手間がどの程度増えるかの目安。
⚠ バブル・選択・挿入は n² に比例。クイック(平均)・マージ・ヒープは n log n に比例。

このレッスンの過去問

このレッスンで稽古する