基本情報技術者試験に頻出のソートをサンプルデータで整理する

基本情報技術者試験(特に科目B)では、ソートアルゴリズムについて 名前の暗記 よりも、

  • この処理は何をしているのか
  • この for 文・while 文で配列はどう変化するのか

を読み取れるかが問われます。

そこで本記事では、最初に共通のサンプルデータを定義し、各ソートがそのデータをどう並び替えるかを確認していきます。


サンプルデータ(全ソート共通)

以降の説明では、次の配列を例として使用します。

A = [ 5, 2, 4, 1, 3 ]

この配列を 昇順(小さい順) に並び替えることを考えます。

最終的な正解は次の形です。

[ 1, 2, 3, 4, 5 ]

1. バブルソート(Bubble Sort)

考え方

  • 隣り合う要素を比較する
  • 順番が逆なら入れ替える
  • 大きい値が右端に押し出されていく

擬似コード例

for i ← 1 to N - 1
  for j ← 1 to N - i
    if A[j] > A[j + 1] then
      TEMP ← A[j]
      A[j] ← A[j + 1]
      A[j + 1] ← TEMP
    endif
  endfor
endfor

サンプルデータでの動き(イメージ)

初期状態

[ 5, 2, 4, 1, 3 ]

1回目の外側ループ後

[ 2, 4, 1, 3, 5 ]

👉 最大値 5 が右端に確定


ポイント

  • 隣同士を比較して交換
  • 動きは単純だが比較回数が多い

2. 選択ソート(Selection Sort)

考え方

  • 未整列部分から最小値を探す
  • それを先頭と交換する
  • 左から順に位置を確定させる

擬似コード例

for i ← 1 to N - 1
  min ← i
  for j ← i + 1 to N
    if A[j] < A[min] then
      min ← j
    endif
  endfor
  TEMP ← A[i]
  A[i] ← A[min]
  A[min] ← TEMP
endfor

サンプルデータでの動き

初期状態

[ 5, 2, 4, 1, 3 ]

1回目(最小値 1 を先頭へ)

[ 1, 2, 4, 5, 3 ]

👉 先頭から順に確定していく


3. 挿入ソート(Insertion Sort)

考え方

  • 左側はすでに整列済みと考える
  • 新しい要素を正しい位置に挿し込む
  • トランプを並べるイメージ

擬似コード例

for i ← 2 to N
  key ← A[i]
  j ← i - 1
  while j ≥ 1 and A[j] > key
    A[j + 1] ← A[j]
    j ← j - 1
  endwhile
  A[j + 1] ← key
endfor

サンプルデータでの動き(途中)

[ 5 | 2, 4, 1, 3 ]
→ [ 2, 5 | 4, 1, 3 ]
→ [ 2, 4, 5 | 1, 3 ]

👉 要素をずらしながら挿入


4. クイックソート(Quick Sort)

考え方

  • 基準値(ピボット)を1つ選ぶ
  • 小さいグループと大きいグループに分割
  • 同じ処理を繰り返す

擬似コード例(概念)

if 配列の要素数 > 1 then
  pivot を選ぶ
  pivotより小さい配列 L
  pivotより大きい配列 R
  QuickSort(L)
  QuickSort(R)
endif

クイックソートを具体化して書きますね。

ポイントは

  • 「LENGTH」
  • 配列の添字(1始まり)
  • 再帰
  • 配列の結合

です。


① 基本情報でよく使われる前提(擬似言語の約束)

  • 配列の添字:1 から始まる
  • LENGTH(A):配列 A の要素数
  • ←:代入
  • []:配列
  • APPEND(X, v):配列 X の末尾に v を追加
  • +:配列の結合

② クイックソートの疑似コード(関数形式)

クイックソート本体

FUNCTION QuickSort(A)
  N ← LENGTH(A)

  IF N ≤ 1 THEN
    RETURN A
  ENDIF

  pivot ← A[1]

  L ← []   // pivot より小さい要素
  R ← []   // pivot より大きい要素

  FOR i ← 2 TO N
    IF A[i] < pivot THEN
      APPEND(L, A[i])
    ELSE
      APPEND(R, A[i])
    ENDIF
  ENDFOR

  L ← QuickSort(L)
  R ← QuickSort(R)

  RETURN L + [pivot] + R
ENDFUNCTION

👉 試験で非常に典型的な形です。


③ 与えられた配列での実行例

A ← [ 5, 2, 4, 1, 3 ]
A ← QuickSort(A)

処理の流れ(概念)

1回目

  • pivot = 5
  • L = [2, 4, 1, 3]
  • R = []

2回目(L に対して)

  • pivot = 2
  • L = [1]
  • R = [4, 3]

3回目(R に対して)

  • pivot = 4
  • L = [3]
  • R = []

最終結果

[1, 2, 3, 4, 5]

④ 出力(質問にあった print)

print A[1]
print A[2]
print A[3]
print A[4]
print A[5]

出力結果:

1
2
3
4
5

⑤ 試験対策としての重要ポイント

✔ pivot は 先頭要素として書かれることが多い

✔ in-place(交換型)より 配列分割型が試験向き

✔ LENGTH は 普通に使ってOK

✔ 再帰終了条件は N ≤ 1


⑥ よくある出題パターン

  • 「この疑似コードの処理回数は?」
  • 「pivot が常に最大だった場合の計算量は?」
  • 「L と R の中身を問う問題」
  • 「再帰呼び出しの回数」

サンプルデータでの分割例

pivot = 3
[ 2, 1 ] | 3 | [ 5, 4 ]

👉 基準で分ける発想が重要


5. マージソート(Merge Sort)

考え方

  • 配列を半分に分ける
  • 小さな配列を整列
  • 最後にマージする

擬似コード例(概念)

if 配列の要素数 > 1 then
  左半分 L
  右半分 R
  MergeSort(L)
  MergeSort(R)
  L と R をマージ
endif

マージソートの疑似コードを、クイックソートと同じ粒度で整理します。


① 擬似言語の前提(前回と同じ)

  • 添字は 1 始まり
  • LENGTH(A):配列の要素数
  • ←:代入
  • []:配列
  • APPEND(X, v):末尾追加

② マージソート全体の疑似コード

MergeSort(分割する側)

FUNCTION MergeSort(A)
  N ← LENGTH(A)

  IF N ≤ 1 THEN
    RETURN A
  ENDIF

  mid ← N DIV 2

  L ← A[1] ~ A[mid]
  R ← A[mid + 1] ~ A[N]

  L ← MergeSort(L)
  R ← MergeSort(R)

  RETURN Merge(L, R)
ENDFUNCTION

③ マージ処理の疑似コード(ここが超重要)

FUNCTION Merge(L, R)
  i ← 1
  j ← 1
  M ← []

  WHILE i ≤ LENGTH(L) AND j ≤ LENGTH(R)
    IF L[i] ≤ R[j] THEN
      APPEND(M, L[i])
      i ← i + 1
    ELSE
      APPEND(M, R[j])
      j ← j + 1
    ENDIF
  ENDWHILE

  WHILE i ≤ LENGTH(L)
    APPEND(M, L[i])
    i ← i + 1
  ENDWHILE

  WHILE j ≤ LENGTH(R)
    APPEND(M, R[j])
    j ← j + 1
  ENDWHILE

  RETURN M
ENDFUNCTION

👉 試験で問われるのは、ほぼこの Merge の中身です。


④ 例:配列での実行

A ← [ 5, 2, 4, 1, 3 ]
A ← MergeSort(A)

分割の流れ

[5, 2, 4, 1, 3]
 → [5, 2] と [4, 1, 3]

[5, 2] → [5] と [2]
[4, 1, 3] → [4] と [1, 3]

マージの流れ

[5] + [2] → [2, 5]
[1] + [3] → [1, 3]
[4] + [1, 3] → [1, 3, 4]
[2, 5] + [1, 3, 4] → [1, 2, 3, 4, 5]

⑤ 出力例(print)

print A[1]
print A[2]
print A[3]
print A[4]
print A[5]

出力:

1
2
3
4
5

⑥ クイックソートとの比較(試験超重要)

項目クイックソートマージソート
分割pivot 基準半分に分割
マージ不要必要
安定性不安定安定
計算量平均 O(N log N)常に O(N log N)
追加領域少なめ多い

⑦ 試験での頻出ポイント

✔ mid ← N DIV 2

✔ Merge の while 条件

✔ 片方が先に尽きた後の 残り要素処理

✔ 計算量は 常に O(N log N)


サンプルデータの流れ

[5, 2, 4, 1, 3]
→ [5, 2] と [4, 1, 3]
→ 整列後に統合

まとめ(基本情報向け)

  • ソートは 暗記するものではない
  • サンプルデータを頭に置き、
    • どこが確定するか
    • 何を比較しているかを追うことが重要

👉 「この処理を実行した後、配列はどうなるか」

これが基本情報で最もよく問われます。


訪問数 122 回, 今日の訪問数 1回