ITパスポート 2023年 問60
問題文
手続printArrayは、配列integerArrayの要素を並べ替えて出力する。手続printArrayを呼び出したときの出力はどれか。ここで、配列の要素番号は1から始まる。
〔プログラム〕
○printArray()
整数型: n, m
整数型の配列: integerArray ← {2, 4, 1, 3}
for (nを1から(integerArrayの要素数− 1)まで1ずつ増やす)
for (mを1から(integerArrayの要素数− n)まで1ずつ増やす)
if (integerArray[m] > integerArray[m + 1])
integerArray[m]とintegerArray[m + 1]の値を入れ替える
endif
endfor
endfor
integerArrayの全ての要素を先頭から順にコンマ区切りで出力する
選択肢
ア:1,2,3,4(正解)
イ:1,3,2,4
ウ:3,1,4,2
エ:4,3,2,1
🔒 解説は解答すると表示されます
手続printArrayは配列を並べ替えて出力する問題【ITパスポート 解説】
正解の理由
与えられた手続は、隣り合う要素を比較して大きければ入れ替える操作を繰り返しています。これは「バブルソート(bubble sort:隣り合う要素を交換していき、大きい要素が泡のように末尾へ移動する単純な整列法)」です。配列は最終的に昇順(小さい順)に並びます。初期配列が {2, 4, 1, 3} なので、昇順にすると 1,2,3,4 となり、したがって選択肢 ア が正しい出力です。
解法ステップ
手順・変数の意味をかみくだいて説明します。
- 配列の要素番号は1から始まる(問題文の指定)。
- 外側のループ n は 1 から (要素数−1) まで回る。
- 内側のループ m は 1 から (要素数 − n) まで回り、integerArray[m] と integerArray[m+1] を比較して大きければ入れ替える。
- これを繰り返すと配列は昇順に整列する(バブルソートの働き)。
実際の配列の変化(各比較・入れ替えごと)
初期: {2, 4, 1, 3}
n = 1(内側 m = 1..3)
- m=1: 比較 2 と 4 → 2 > 4? いいえ → {2,4,1,3}
- m=2: 比較 4 と 1 → 4 > 1? はい → 入れ替え → {2,1,4,3}
- m=3: 比較 4 と 3 → 4 > 3? はい → 入れ替え → {2,1,3,4}
n = 2(内側 m = 1..2)
- m=1: 比較 2 と 1 → 2 > 1? はい → 入れ替え → {1,2,3,4}
- m=2: 比較 2 と 3 → 2 > 3? いいえ → {1,2,3,4}
n = 3(内側 m = 1)
- m=1: 比較 1 と 2 → 1 > 2? いいえ → {1,2,3,4}
最終出力:1,2,3,4(選択肢 ア)
(補足)比較回数は 3 + 2 + 1 = 6 回です。
選択肢別の誤答解説
- ア(1,2,3,4): 正解。上の手順どおり最終的に昇順に整列する。
- イ(1,3,2,4): これは一部だけ入れ替わった状態です。完全に昇順になっていないため誤りです。バブルソートは複数回のパスで確実に並べ替えるため、この途中状態で終了することはありません。
- ウ(3,1,4,2): 元の並び {2,4,1,3} を部分的にランダムに入れ替えたものです。与えられた交換規則(隣接比較で大きければ交換)からはこの順序にはなりません。
- エ(4,3,2,1): これは降順(大きい順)です。問題の比較は「大きければ交換」しているため、大きい値は右側へ移動し最終的に昇順になります。従って降順にはなりません。
よくある誤解
- 配列番号を0から始まると勘違いする
- 問題は「要素番号は1から始まる」と明記しています。これはインデックス計算に影響します(この問題では m と m+1 の範囲が正しく動作することを保証します)。
- 一回の内側ループ(1パス)で整列が終わると考える
- バブルソートでは複数パスが必要です。最初のパスで最大値が末尾に移動しますが、残りはまだ乱れています。
- 比較条件を逆に解釈する(大きければ交換 → 昇順になること)
- 「大きければ右へ送る」処理は結果として昇順になります。逆の条件なら降順になります。
補足コラム
- バブルソートの特徴
- 安定なソート:等しい要素の相対順序は保たれる(stable)。
- インプレース:追加の大きな記憶領域を必要としない。
- 計算量は一般に (要素数 に対して二重ループ)。小さい配列では理解しやすく使いやすいですが、大きなデータには不向きです。
- 最適化
- 途中で交換が一度も起きなければ(既に整列済み)終了するようにすると平均処理を早められます。
- 名前の由来:大きな値がどんどん「泡(bubble)」のように末尾へ浮かんでいく様子に由来します。
簡単な実装例(Python)
# 1から始まるインデックスを意識せずにPythonで同じ動作をさせる例
arr = [2,4,1,3]
n = len(arr)
for i in range(n-1):
for j in range(n-1-i):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
print(','.join(map(str, arr))) # 出力: 1,2,3,4
FAQ
Q. 内側ループの終わりが (要素数 − n) なのはなぜですか?
A. 外側ループを1回行うごとに配列の末尾に正しい要素(その時点での最大値)が一つ確定します。したがって次のパスでは末尾の確定済み要素を比較対象から外せます。これが (要素数 − n) の理由です。
A. 外側ループを1回行うごとに配列の末尾に正しい要素(その時点での最大値)が一つ確定します。したがって次のパスでは末尾の確定済み要素を比較対象から外せます。これが (要素数 − n) の理由です。
Q. 同じ値が複数ある場合はどうなりますか?
A. このアルゴリズムは安定なソートなので、同値の要素の元の順序は維持されます。
A. このアルゴリズムは安定なソートなので、同値の要素の元の順序は維持されます。
Q. より速いソートはありますか?
A. はい。例えばクイックソートやマージソートは平均 で、大きなデータに向いています。ただし実装の手軽さや小規模データではバブルソートが学習用途として有用です。
A. はい。例えばクイックソートやマージソートは平均 で、大きなデータに向いています。ただし実装の手軽さや小規模データではバブルソートが学習用途として有用です。
関連キーワード: バブルソート、配列、交換(スワップ)、昇順、ループ構造、安定ソート、計算量、インプレース、要素番号1から始まる、比較ソート

\ せっかくなら /
ITパスポートを
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

