選択ソートとは?
未ソート(未整列)のデータの中から**「最小値(または最大値)」を探し出し、それを未ソート部分の先頭要素と入れ替える**操作を繰り返すアルゴリズムです。
直感的に「一番小さいものを順に選んで並べていく」ため、仕組みが非常に理解しやすいのが特徴です。
処理の流れ(アルゴリズムの手順)
配列 [6, 4, 8, 3] を昇順(小さい順)に並べ替える例で流れを確認します。
【初期状態】
i=0
↓
[ 6 , 4 , 8 , 3 ] ← 未ソート部全体から最小値「3」を探す
↑ 最小値の位置
--- パス 1 ---
[ 3 | 4 , 8 , 6 ] ← 「3」と「6」を交換。「3」が確定!
↑確定
--------------------------------------------------
i=1
↓
[ 3 | 4 , 8 , 6 ] ← 未ソート部 [4, 8, 6] から最小値「4」を探す
↑ 最小値の位置
--- パス 2 ---
[ 3 , 4 | 8 , 6 ] ← 自分自身(4)が最小値なのでそのまま確定!
↑確定
--------------------------------------------------
i=2
↓
[ 3 , 4 | 8 , 6 ] ← 未ソート部 [8, 6] から最小値「6」を探す
↑ 最小値の位置
--- パス 3 ---
[ 3 , 4 , 6 | 8 ] ← 「6」と「8」を交換。「6」が確定!
↑確定
--------------------------------------------------
【完了】
[ 3 , 4 , 6 , 8 ] ← 最後の1つ(8)も自動的に確定しソート完了
未整列データからアルゴリズムで最小値を探索する方法
未整列の配列(リスト)から最小値を探索する最も基本かつ確実な手法は、**線形探索(Linear Search)**を用いて全要素を1回ずつ確認していくアプローチです。
探索アルゴリズムの考え方
日常の例で例えると、「一番安い商品を探すために、値札を1枚ずつ順番に確認し、それまでの最安値を手帳にメモしていく」作業と同じです。
-
仮の最小値を決める
配列の先頭要素(インデックス0)を「現在の最小値」と仮定し、その値(またはインデックス)を保持します。 -
先頭から順番に比較する
2番目の要素(インデックス1)から順に末尾まで1つずつ比較していきます。 -
より小さな値があれば更新する
チェック中の要素が「保持している最小値」よりも小さければ、保持する情報をその要素で上書きします。 -
全体のチェックを終える
すべての要素を一度確認し終えた時点で保持されている情報が、配列全体の「最小値」となります。
トレース例(テキスト図解)
配列 [6, 4, 8, 3, 7] から最小値を探索する流れです。
【初期設定】
先頭の「6」を仮の最小値に設定
min_idx = 0 (値: 6)
【1ステップ目】i = 1(値: 4)
4 と 6(min) を比較 → 4 の方が小さい!
min_idx を 1 (値: 4) に更新
【2ステップ目】i = 2(値: 8)
8 と 4(min) を比較 → 4 の方が小さい(変化なし)
min_idx は 1 のまま
【3ステップ目】i = 3(値: 3)
3 と 4(min) を比較 → 3 の方が小さい!
min_idx を 3 (値: 3) に更新
【4ステップ目】i = 4(値: 7)
7 と 3(min) を比較 → 3 の方が小さい(変化なし)
min_idx は 3 のまま
【探索完了】
配列の末尾まで確認終了。最小値はインデックス 3 の「3」
# 【Python】配列から最小値の位置(インデックス)を探索する関数
配列(リスト)から「最小値そのもの」ではなく、選択ソートなどで必要となる**「最小値が置かれているインデックス」**を探索するコードの解説です。
実装コード
def find_min_index(a):
"""配列 a から最小値のインデックスを探索して返す"""
min_idx = 0 # 仮の最小値の位置を先頭に設定
# 2番目の要素(インデックス1)から末尾まで順に走査
for i in range(1, len(a)):
if a[i] < a[min_idx]:
min_idx = i # より小さい値が見つかったらインデックスを更新
return min_idx
# 動作確認
data = [6, 4, 8, 3, 7]
idx = find_min_index(data)
print(f"最小値の位置(インデックス): {idx}") # 3
print(f"最小値: {data[idx]}") # 3
実務ではどのように使われるのか
選択ソートは一般的なシステムやアプリケーションの開発実務で使われることは基本的にはない。すでに標準ライブラリとして高速で働くアルゴリズムがあるため。
ただし、学習においては、
- 状態の分割(境界線)という発想
- 最小値・最大値探索の基本
という「思考体力」としての価値はある。
処理過程(配列の変化・最小値・交換)を観察するコード
def selection_sort_verbose(a):
"""単純選択ソート(処理過程を表示)"""
n = len(a)
print(f"初期状態: {a}\n" + "=" * 40)
for i in range(n - 1):
min_idx = i
print(f"--- パス {i + 1} (インデックス {i} の確定を目指す) ---")
# 未ソート部から最小値を探索
for j in range(i + 1, n):
if a[j] < a[min_idx]:
min_idx = j
print(f" 未ソート部の最小値: {a[min_idx]} (位置: {min_idx})")
# 要素の交換
a[i], a[min_idx] = a[min_idx], a[i]
print(f" 交換後の配列: {a}\n")
# 動作確認
data = [6, 4, 8, 3, 1]
selection_sort_verbose(data)
def selection_sort_with_stats(a):
"""比較回数と交換回数を計測する選択ソート"""
n = len(a)
compare_count = 0 # 比較回数
swap_count = 0 # 交換回数
for i in range(n - 1):
min_idx = i
for j in range(i + 1, n):
compare_count += 1
if a[j] < a[min_idx]:
min_idx = j
# 実際に位置が変わる場合のみ交換(最適化)
if min_idx != i:
a[i], a[min_idx] = a[min_idx], a[i]
swap_count += 1
return compare_count, swap_count
# 動作確認
data = [6, 4, 8, 3, 1, 9, 7]
ccnt, scnt = selection_sort_with_stats(data)
print(f"ソート結果: {data}")
print(f"比較回数: {ccnt} 回")
print(f"交換回数: {scnt} 回")
- 比較回数:データサイズのnの2乗に比例する。
- 交換回数:データサイズnに比例する。

