IT1-CODE-POCKET

選択法(選択ソート)シミュレーター

選択法は、未整列の部分から最小値を探し、その位置と先頭を1回だけ交換する整列です。 min_pos が最小値の位置を追いかける様子を1ステップずつ止めて確認できます。

動きを1ステップずつ確認する

要素数(個)
並び
配列 Nums
    • 比較(j)
    • 最小の候補
    • 交換
    • 確定

    i=確定させる位置/m=min_pos/j=調べている位置

    i
    min_pos
    j
    比較 0
    交換 0
    STEP 1 / 1 読み込み中です。

    パソコンではキーボードでも操作できます: 次へ / 前へ / スペース 再生・一時停止

    数値を自分で入力する

    カンマ区切りで 0〜99 の整数を入力します。

    実行ログを見る(ここまでの処理)

      ALGORITHM

      選択法とは何をしているか

      選択法(選択ソート)は、まだ整列していない部分の中からいちばん小さい値を選び、その部分の先頭と交換するという操作を繰り返す整列です。 1回のパスで先頭から1個ずつ確定していくため、交換法(右端から確定)とは確定していく向きが逆になります。

      トランプを並べ替えるとき、「残りの中でいちばん小さいカードを探して、左端に置く」という作業を繰り返すのと同じです。 シミュレーターでは、探している範囲を j(青)が動き、現在の最小値の候補が黄色で示されます。

      min_pos は「値」ではなく「位置」を覚える

      このアルゴリズムの中心にあるのが min_pos です。名前のとおり最小値の位置(添字)を覚えます。 なぜ値ではなく位置なのかというと、最後に交換するときに「どこにあるか」が分からなければ入れ替えられないからです。 「いちばん小さいのは 1 だ」と分かっても、それが配列のどこにあるか分からなければ Nums[i] と交換できません。

      確認方法:シミュレーターで、より小さい値が見つかったときに min_pos の値が 「その位置の添字」に変わることを確認してください。黄色いマスも一緒に移動します。

      内側の繰り返しは i + 1 から

      内側の ji + 1 から始まります。i 自身はすでに min_pos = i として候補になっているので、 自分と自分を比べる必要がないからです。また i より前は確定済みなので、調べる範囲は自然と後ろへ狭まっていきます。

      1パスで交換は1回だけ

      交換法との最大の違いがここです。交換法は条件が成り立つたびに入れ替えるので交換が何度も起きますが、 選択法は探し終わってから1回だけ交換します。そのため交換回数は多くても n - 1 回で済みます。

      項目 交換法(バブルソート) 選択法(選択ソート)
      比較回数 n(n-1)/2 回 n(n-1)/2 回(同じ)
      交換回数(最大) n(n-1)/2 回 n - 1 回
      確定する向き 右端(最大値)から 左端(最小値)から
      覚える変数 なし(その場で交換) min_pos(最小値の位置)
      計算量 O(n²) O(n²)(同じ)

      要素数5の逆順で比べると、交換法は10回交換しますが、選択法は2回で済みます。 交換法のシミュレーターと見比べてみてください。

      すでに整列済みでも交換は起きる

      基本の書き方では、min_posi と同じでも交換の3行を実行します。これは同じ位置どうしの交換なので値は変わりませんが、 交換回数としては数えられます。無駄を省きたい場合は もし min_pos != i ならば という条件を足します。 条件の切り替えで、整列済みの配列の交換回数が 4回 → 0回(要素数5のとき)に変わることを確認できます。

      CODE

      3つの書き方で見る選択法

      Nums = [5, 2, 4, 1]
      
      i を 0 から 要素数(Nums) - 2 まで 1 ずつ増やしながら繰り返す:
      |min_pos = i
      |j を i + 1 から 要素数(Nums) - 1 まで 1 ずつ増やしながら繰り返す:
      ||もし Nums[j] < Nums[min_pos] ならば:
      |⎿⎿ min_pos = j
      |temp = Nums[i]
      |Nums[i] = Nums[min_pos]
      ⎿ Nums[min_pos] = temp
      
      表示する(Nums)
      交換の3行は交換法と同じ:temp に退避してから入れ替える手順は、 交換法とまったく同じです。違うのは交換する相手で、 交換法は「隣(j と j+1)」、選択法は「先頭と最小値の位置(i と min_pos)」です。

      COST

      比較回数と計算量

      要素数 比較回数 交換回数(最大) 計算量
      4 個 6 回 3 回 O(n²)
      5 個 10 回 4 回 O(n²)
      10 個 45 回 9 回 O(n²)
      n 個 n(n-1)/2 回 n - 1 回 O(n²)

      比較回数は交換法とまったく同じで、並び方に関係なく一定です。 違うのは交換回数だけで、こちらは要素数に比例する程度(n - 1 回)に抑えられます。 ただし処理全体の重さは比較回数が決めるため、計算量はどちらも O(n²) です。 「交換が少ない=速い」と単純に言えない点に注意してください。

      EXAM POINT

      共通テスト「情報Ⅰ」での出題ポイント

      1. min_pos の更新:min_pos = j の行が空欄になる形。値ではなく位置を代入する点が要点です。
      2. 内側の開始値:j を i + 1 からi + 1 の部分。なぜ i からではないのかを問われます。
      3. 比較の向き:Nums[j] < Nums[min_pos] の不等号。> にすると最大値を探すことになり、大きい順に並びます。
      4. 1パス後の配列:「1回目のパスが終わった時点の配列」を答える問題。先頭が確定する点が交換法との違いです。
      5. 交換回数の比較:「交換法と選択法で交換回数が少ないのはどちらか」という比較問題。選択法は最大 n - 1 回です。
      交換法と混同しないコツ:確定していく向きで見分けられます。 選択法は左から(最小値から)、交換法は右から(最大値から)確定します。 シミュレーターで緑のマスが増えていく向きを見比べてください。

      MISTAKES

      よくある間違い

      間違い 何が起きるか 正しくは
      min_pos に値を入れる 交換するときにどこにあるか分からない 位置(添字)を入れる
      見つけるたびに交換する 交換回数が増え、選択法ではなくなる 探し終わってから1回だけ交換する
      内側を i から始める 自分と自分を比べる無駄が生じる i + 1 から始める
      min_pos の初期化を忘れる 前のパスの位置が残り、正しく並ばない パスの最初に min_pos = i と設定する
      外側を要素数 - 1 まで回す 最後の1個で無駄な処理をする 要素数 - 2 まで(最後の1個は自動的に決まる)

      CHECK

      理解度チェック

      Q1. Nums = [5, 2, 4, 1] で、1回目のパスが終わった時点の配列はどうなりますか。
      [1, 2, 4, 5]。 最小値 1(添字 3)を見つけ、先頭の 5 と交換します。先頭が確定する点が、 交換法(1パス後は [2, 4, 1, 5] で右端が確定)との違いです。
      Q2. 要素数5の逆順 [5, 4, 3, 2, 1] のとき、交換回数は何回ですか。
      4回(基本の書き方)。 1パスにつき1回しか交換しないので、パスの数(要素数 - 1 = 4)と同じになります。 同じ配列を交換法で処理すると10回なので、交換回数には大きな差が出ます。
      Q3. すでに整列済みの [1, 2, 3, 4, 5] のとき、比較回数と交換回数はいくつですか。
      比較 10 回、交換 4 回(基本の書き方)。 すでに並んでいても、最小値を探すための比較は最後まで行われます。 交換は毎回「同じ位置どうし」なので値は変わりませんが、回数としては数えます。 「min_pos が i と同じなら交換しない」を選ぶと交換 0 回になります。
      Q4. 条件を Nums[j] > Nums[min_pos] に変えると、どう並びますか。
      大きい順(降順)に並びます。 探すものが最小値から最大値に変わるため、先頭から大きい順に確定していきます。 変数名は min_pos のままでも動きますが、意味は「最大値の位置」になります。

      次に確認したいアルゴリズム