【科目B対策】最大値の位置を使って配列の要素を入れ替えるアルゴリズム

2026年2月3日

― 選択ソートの核心 ―

これまでに学んだことを整理します。

  • 配列を順に見て最大値を求める
  • 最大値の 位置(添字) を求める

ここまでできると、次に必ず出てくるのが

最大値を、正しい位置に移動させる

という処理です。

これは 選択ソート(Selection Sort) の最重要部分であり、

科目Bで非常に出題されやすいアルゴリズムです。


目次

まずは配列の例

A ← [ 7, 3, 9, 4, 6 ]
N ← LENGTH(A)

今回は、

  • 最大値を探す
  • 見つかった最大値を 末尾と入れ替える

という処理を行います。


なぜ「末尾」と入れ替えるのか?

配列を並び替えるとき、

  • 最大値 → 一番右
  • 最小値 → 一番左

に置いていくと、

確定した部分が増えていくためです。

選択ソートでは、

「未整列の範囲」から最大値を探し、末尾に確定させる

という操作を繰り返します。


単発:最大値と末尾を入れ替える擬似コード

まずは 1回分の処理 を見ます。

最大値の位置を求める

MAX ← A[1]
MAX_POS ← 1

for i ← 2 to N
  if A[i] > MAX then
    MAX ← A[i]
    MAX_POS ← i
  endif
endfor

最大値と末尾を入れ替える

TEMP ← A[N]
A[N] ← A[MAX_POS]
A[MAX_POS] ← TEMP

これで、

[ 7, 3, 9, 4, 6 ]

は、

[ 7, 3, 6, 4, 9 ]

になります。

最大値 9 が末尾に確定しました。


科目Bで超重要:なぜ TEMP が必要か?

次のように書きたくなりがちですが、

A[N] ← A[MAX_POS]
A[MAX_POS] ← A[N]

これは 誤りです。

1行目で A[N] の元の値が失われるためです。


正しい考え方

  • 一時的に退避させる変数(TEMP)を使う
  • 3ステップで交換する
TEMP ← A[N]
A[N] ← A[MAX_POS]
A[MAX_POS] ← TEMP

👉 この形は 科目B頻出テンプレート です。


選択ソートとして拡張する

ここまでの処理を「繰り返す」と、選択ソートになります。

科目B風 擬似コード(最大値版)

A ← [ 7, 3, 9, 4, 6 ]
N ← LENGTH(A)

for last ← N downto 2
  MAX ← A[1]
  MAX_POS ← 1

  for i ← 2 to last
    if A[i] > MAX then
      MAX ← A[i]
      MAX_POS ← i
    endif
  endfor

  TEMP ← A[last]
  A[last] ← A[MAX_POS]
  A[MAX_POS] ← TEMP
endfor

for i ← 1 to N
  print A[i]
endfor

処理のイメージ

1回目

→ 最大値を A[N] に確定

2回目

→ 残り(A[1]〜A[N-1])から最大値を探す

3回目

→ さらに範囲を狭める

このように、確定領域が右から増えていくのが特徴です。


この処理は、次のことを 繰り返し 行っています。

  1. 配列の中から 最大値を探す
  2. 見つけた最大値を 右端(last番目)に移動
  3. 右端を「確定」として、探索範囲を狭める

これを 右から順に 確定させていくのが選択ソート(最大値版)の考え方です。


初期状態

A ← [ 7, 3, 9, 4, 6 ]
N ← 5
添字12345
73946

※ 基本情報試験では、配列の添字が 1 から始まる指定がよくあります。


1回目の処理(last = 5)

最大値を探す

初期状態:

MAX = 7
MAX_POS = 1
iA[i]MAX判定
237更新なし
397MAX=9, POS=3
449更新なし
569更新なし

👉 最大値は 9(位置3)


最大値を右端と交換

A[5] と A[3] を交換
[ 7, 3, 6, 4, 9 ]

👉 9 が確定(もう動かない)


2回目の処理(last = 4)

探索範囲は 1~4番目

最大値探索の結果:

  • 最大値:7(位置1)

交換後:

[ 4, 3, 6, 7, 9 ]

👉 7 と 9 が確定


3回目の処理(last = 3)

探索範囲は 1~3番目

  • 最大値:6(位置3)
  • 同じ位置なので交換後も変化なし
[ 4, 3, 6, 7, 9 ]

4回目の処理(last = 2)

探索範囲は 1~2番目

  • 最大値:4(位置1)

交換後:

[ 3, 4, 6, 7, 9 ]

最終結果

3
4
6
7
9

配列は昇順に並び替えられました。


ポイント①:last の意味を理解する

  • last は 「まだ並び替えていない範囲の右端」
  • last が小さくなるほど、右側は確定していく

ポイント②:毎回やっている処理は同じ

  1. 最大値を A[1] に仮定
  2. 範囲内で最大値を探す
  3. last 番目と交換

👉 回数が変わるだけで、処理内容は変わらない


ポイント③:試験では「動き」を問われる

基本情報技術者試験(科目B)では、

  • 「何回目のループ後の配列」
  • 「この時点で確定している要素」
  • 「交換後の配列の状態」

といった トレース力 が問われます。

コードを丸暗記するよりも、

紙に書いて追えるか を意識しましょう。


まとめ

  • 選択ソート(最大値版)は「右から確定」
  • last が示す範囲を意識すると理解しやすい
  • トレースできれば試験問題は解ける

基本情報技術者試験(CBT)では、

白紙のメモ用紙とペンが渡されます。

このメモは

👉 「計算を書く紙」ではなく「考えるための補助脳」

として使うのが正解です。


① 絶対にやってはいけないメモ

❌ コードを全文書き写す

❌ きれいに書こうとする

❌ 日本語の説明文を書く

→ 時間を失うだけで得点につながりません


② 有効なメモの基本方針(重要)

メモに書くのは、次の3つだけです。

  1. 配列の状態
  2. 今見ている範囲
  3. 確定した要素

③ 選択ソート問題のメモサンプル

問題例(頭の中)

A = [ 7, 3, 9, 4, 6 ]

メモ用紙に最初に書くもの

[7][3][9][4][6]
 1  2  3  4  5

※ 添字は 必ず書く(試験では超重要)


④ 1回目の処理(last = 5)

メモの書き方

[7][3][9][4][6] |  ← 5
  • | より右は 確定
  • 今はまだ確定なし

最大値を探す → 9(3番)

交換後:

[7][3][6][4] | [9]

👉 9 確定


⑤ 2回目の処理(last = 4)

[7][3][6][4] | [9]

最大値 → 7(1番)

交換後:

[4][3][6] | [7][9]

👉 7, 9 確定


⑥ 3回目の処理(last = 3)

[4][3][6] | [7][9]

最大値 → 6(3番)

交換(変化なし):

[4][3] | [6][7][9]

⑦ 4回目の処理(last = 2)

[4][3] | [6][7][9]

最大値 → 4(1番)

交換後:

[3][4][6][7][9]

⑧ 最終メモ(これが答え)

[3][4][6][7][9]

⑨ メモのポイントまとめ(超重要)

ポイント①

1行で書き直すのが正解

  • × 何行も残す
  • ○ 常に「今の状態」だけ残す

ポイント②

縦線「|」は最強の記号

  • 左:未処理
  • 右:確定

👉 言葉より速い


ポイント③

if 文や for 文は一切書かない

  • コードは画面にある
  • メモは「変化」だけを書く

⑩ 試験でよくある失敗と回避策

失敗回避
添字を忘れる最初に必ず書く
範囲を間違える`
途中で混乱1行だけ残す

⑪ まとめ

  • 科目Bは「暗記試験」ではない
  • メモを使えるかどうかで難易度が変わる
  • 正しいメモは、思考を助けてくれる

科目Bで狙われやすいポイント

① 内側ループの範囲

for i ← 2 to last

ここを N まで回すと 論理破綻します。


② MAX と MAX_POS の初期化位置

for last ← ...
  MAX ← A[1]
  MAX_POS ← 1

👉 外側ループの中で初期化するのが正解。


③ 入れ替えをしないケース

  • すでに最大値が末尾にある→ それでも入れ替え処理は実行される

試験では

「無駄な処理があっても正しいか?」

を問われることがあります。


まとめ(ここは必ず押さえる)

  • 最大値の「位置」が分かると入れ替えができる
  • 入れ替えには TEMP を使う
  • この構造がそのまま選択ソートになる
  • 科目Bでは 範囲・初期化・代入順 が問われる

【問題1】

次の擬似言語は,配列 A の要素を昇順に並べ替える処理である。

A ← [ 7, 3, 9, 4, 6 ]
N ← LENGTH(A)

for last ← N downto 2
  MAX ← A[1]
  MAX_POS ← 1

  for i ← 2 to last
    if A[i] > MAX then
      MAX ← A[i]
      MAX_POS ← i
    endif
  endfor

  TEMP ← A[last]
  A[last] ← A[MAX_POS]
  A[MAX_POS] ← TEMP
endfor

外側の for ループが 1回目(last = 5) の処理を終了した直後の

配列 A の内容として,最も適切なものはどれか。


 [ 7, 3, 6, 4, 9 ]

 [ 6, 3, 7, 4, 9 ]

 [ 3, 4, 6, 7, 9 ]

 [ 7, 3, 9, 4, 6 ]


正解

解説

  • 外側ループ 1 回目ではA[1] ~ A[5] の中から最大値を探す
  • 配列 [ 7, 3, 9, 4, 6 ] の最大値は 9
  • 最大値 9 を 末尾 A[5] に移動
  • したがって,配列は[ 7, 3, 6, 4, 9 ]

👉 この時点で「9」は確定

👉 それ以外の順序はまだ整っていない


【問題2】

問題1と同じ擬似言語において,

外側の for ループが 2回目(last = 4) の処理を終了した直後の

配列 A の内容として,最も適切なものはどれか。


 [ 4, 3, 6, 7, 9 ]

 [ 6, 3, 4, 7, 9 ]

 [ 7, 3, 4, 6, 9 ]

 [ 3, 6, 4, 7, 9 ]

正解:ア

解説

  • 1回目終了時点[ 7, 3, 6, 4, 9 ]
  • 2回目は A[1] ~ A[4] の中で最大値を探す
  • 最大値は 7
  • 7 を A[4] に移動

結果

[ 4, 3, 6, 7, 9 ]

👉 後ろから順に「最大値が確定」していく

👉 これがこの処理の最大の特徴


【問題3】

次の擬似言語中の □ に入れるものとして,最も適切なものはどれか。

for i ← 2 to last
  if A[i] > MAX then
    MAX ← A[i]
    □ ← i
  endif
endfor

 MAX

 TEMP

 MAX_POS

 last


正解

解説

  • MAX には 最大値そのもの を入れている
  • 交換処理には「どこにあったか(添字)」 が必要
  • そのため,位置を記録する変数MAX_POS ← i が正しい

👉 値と位置を混同させるのが典型的なひっかけ


【問題4】

配列の要素数を N とする。

問題1の擬似言語において,

外側の for ループが 1回実行される間に行われる

大小比較(A[i] > MAX)の回数として,最も適切なものはどれか。


 N 回

 N − 1 回

 N − 2 回

 N² 回


正解

解説

  • 内側ループはi ← 2 to last
  • last = N のとき比較回数は2 ~ N → N − 1 回

👉 回数問題は

👉 範囲を図に描けるかどうか が勝負


【問題5】

この処理についての記述として,正しいものはどれか。


 配列全体が常に昇順に並んでいることを前提としている

 各外側ループの終了時に,最大値が先頭に確定する

 各外側ループの終了時に,最大値が末尾に確定する

 常に隣接する要素同士を比較している


正解

解説

  • 各外側ループの目的は探索範囲の最大値を末尾に移動すること
  • 隣同士の比較ではない → バブルソートではない
  • 昇順が途中で完成するわけではない

👉 「末尾に確定」=このコードの核


まとめ(試験で勝つために)

  • 名前は覚えなくていい
  • 見るべきは常にこの3点
    1. 今回の探索範囲
    2. 何が確定したか
    3. 値と位置の役割分担

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