edubun
日本語

ソート1:バブルソート、選択ソート、挿入ソート

選択ソートは、10個の値のリストならどんなものでも、はじめがばらばらでもすでに整列していても、ちょうど45回比較します。

順番に並べる

ソート(整列)とは、リストの値が小さいものから大きいものへ(あるいは名前順、日付順、値段順など、比べられるどんな順でも)並ぶように並べかえることです。コンピューターがする仕事の中でも特によくあるものです。スマートフォンの連絡先、関連の高い順に並んだ検索結果、日付順に並べたスプレッドシートの列などがそうです。ソートは、ほかの仕事も楽にします。前のユニットで見たように、整列したリストは二分探索で探せますし、整列したリストでは重複した値が隣どうしに並びます。

このユニットでは3つの簡単な方法を扱います。どれも2つの値を一度に比べ、同じリストの中で値を動かして進めます。短く書けて追いやすいのですが、3つとも長いリストでは急に遅くなります。なぜ遅くなるのかを見ておくことが、次のユニットのもっと速い方法へのいちばんの準備になります。ここではずっと、比較(「この値はあの値より大きいか?」と問うこと)と交換(2つの値を入れかえること)の2つを数えます。

バブルソート:順番が逆の隣どうしを交換する

バブルソートは、リストにそって隣どうしの組を順に比べていきます。左のほうが大きければ、2つを交換します。1回の走査が終わると、最大の値が泡が浮かぶように一歩ずつ右端まで運ばれ、もう動かす必要はなくなります。次の走査は1つ手前で止められます。よくある改良は、交換が1回もない走査に気づくことです。それはすべてがもう順に並んでいるという意味なので、ソートを早めに終えられます。

リスト [5, 1, 4, 2, 8] で追ってみましょう。1回目の走査では、5と1(交換)、5と4(交換)、5と2(交換)、5と8(そのまま)を比べます。リストは [1, 4, 2, 5, 8] になり、8は正しい位置に来ました。2回目の走査では1と4、4と2(交換)、4と5を比べて、[1, 2, 4, 5, 8] になります。3回目の走査では1と2、次に2と4を比べ、交換がないので止まります。合計は比較 4 + 3 + 2 = 9 回、交換4回です。

function bubbleSort(a) {
  for (let pass = 0; pass < a.length - 1; pass++) {
    let swapped = false;
    for (let j = 0; j < a.length - 1 - pass; j++) {
      if (a[j] > a[j + 1]) {
        [a[j], a[j + 1]] = [a[j + 1], a[j]];  // 交換
        swapped = true;
      }
    }
    if (!swapped) break;  // 整列済み
  }
  return a;
}

選択ソート:最小のものを見つけて次に置く

選択ソートは、多くの人が手持ちのトランプを並べるやり方と同じです。リスト全体から最小の値を探し、それを先頭の位置と交換します。次に残りから最小の値を探して2番目の位置と交換し、これを続けます。[5, 1, 4, 2, 8] では、1回目の探索で1を見つけて5と交換し、2回目で2を見つけて5と交換します。最後の2回の探索では、4と5がもう正しい位置にあるとわかります。交換は2回だけですが、探索での比較は 4 + 3 + 2 + 1 = 10 回あります。

選択ソートは途中で止まりません。すでに整列したリストでも、最小の値を手にしていると確かめるために、残りの値をすべて調べなければなりません。n個の値では、比較の回数はいつも (n − 1) + (n − 2) + … + 1 = n(n − 1)/2 になります。10個なら45回、100個なら4,950回、1,000個なら499,500回です。強みは交換の少なさで、多くてもn − 1回です。値を動かすのに手間がかかるときには、これが効いてきます。

挿入ソート:新しい値を正しい位置へすべりこませる

挿入ソートは、リストの左側を整列した状態に保ち、それを1つずつ広げていきます。次の値を取り、隣の値が大きくなくなるまで、隣と交換しながら左へ動かします。するとその値は、整列した値の中で正しい位置に入ります。すでにほぼ整列したリストでは、新しい値はそれぞれ1〜2歩しか動かないので、挿入ソートはとても速くなります。[5, 1, 4, 2, 8] では、比較7回、交換4回です。

読み込み中

ドラッグで回転、スクロールまたはピンチで拡大・縮小。

リスト [5, 1, 4, 2, 8]。3つの方法を切りかえて、このユニットに出てくる回数を確かめましょう。次に「逆順」か「整列済み」を選んで、最善の場合と最悪の場合を見てみましょう。

交換を数える:転倒

バブルソートと挿入ソートの交換の回数を予想する、うまい方法があります。転倒、つまりおたがいの順番が逆になっている値の組を数えるのです。[5, 1, 4, 2, 8] の転倒は (5, 1)、(5, 4)、(5, 2)、(4, 2) の全部で4つです。順番が逆の隣どうしを1回交換すると、転倒がちょうど1つ直り、新しい転倒はできません。だからどちらの方法も、交換はちょうど4回です。n個の値の逆順のリストでは、すべての組が転倒していて、転倒は n(n − 1)/2 個です。これが最悪の場合です。

方法例整列済み(5個)逆順(4個)
バブルソート9 / 44 / 06 / 6
選択ソート10 / 210 / 06 / 2
挿入ソート7 / 44 / 06 / 6

各マスは 比較 / 交換 の回数です。例のリストは [5, 1, 4, 2, 8] です。ここでのバブルソートは、交換のない走査の後で止まる版です。

3つの方法には同じ弱点があります。最悪の場合、どれもほぼすべての値の組を比べ、比較は約 n²/2 回になります。リストを2倍にすると仕事量は4倍になります。リストが10倍なら仕事量は100倍です。数十個の値ならほとんど問題になりませんが、100万個ではお手上げです。次のユニットでは、ずっとうまいやり方を見ていきます。

比較ある値が別の値より大きいかどうかを問うこと
交換2つの値の位置を入れかえること
走査(パス)リストにそって1回通ること
バブルソート順番が逆の隣どうしを交換する。走査のたびに最大の値が端へ上がっていく
選択ソート残りの中の最小の値を見つけ、次の位置と交換する
挿入ソート新しい値を、整列した部分の中へ左にすべりこませる
転倒おたがいの順番が逆になっている値の組
n(n − 1)/2n個の値からできる組の数
  1. 10個の値のリストで、選択ソートは何回比較しますか?
  2. [3, 1, 2] の転倒はいくつありますか?
  3. [4, 3, 2, 1] で挿入ソートは何回交換しますか?
  4. バブルソートの1回目の走査の後、確実に最終的な位置にある値はどれですか?
    • 最小の値(先頭)
    • 最大の値(末尾)
    • 真ん中の値
    • まだどれもない
  5. [5, 1, 4, 2, 8] で交換がいちばん少ないのはどの方法ですか?
    • バブルソート
    • 選択ソート
    • 挿入ソート
  6. リストはすでに整列しています。それでも n(n − 1)/2 回比較するのはどの方法ですか?
    • 途中で止まるバブルソート
    • 選択ソート
    • 挿入ソート
  7. [5, 1, 4, 2, 8] で、(途中で止まる)バブルソートは何回比較しますか?
  8. 1,000個の値のリストが2,000個になりました。挿入ソートの最悪の場合の仕事量は、おおよそどう変わりますか?
    • 2倍になる
    • 約4倍になる
    • 1,000ステップ増える
    • 変わらない
  9. ほぼ整列済みのリストにいちばん向いているのはどの方法ですか?
    • 挿入ソート
    • 選択ソート
    • どれでも同じ
  10. 100個の値から組はいくつ作れますか(最悪の場合の比較回数 n(n − 1)/2)?
  11. リスト [3, 1, 2] が挿入ソートの途中でたどる並びを順に並べましょう。
ポイント
  • バブルソートは隣どうしを交換し、走査のたびに最大の値を末尾へ運びます。
  • 選択ソートの比較はいつも n(n − 1)/2 回で、交換は多くても n − 1 回です。
  • 挿入ソートはほぼ整列したリストで速くなります。
  • バブルソートと挿入ソートは、転倒1つにつき交換を1回行います。
  • 3つとも、最悪の場合は約 n² ステップかかります。
このコースの出典 (11)
  • MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
  • lecture notes 1 Introduction, 3 Sorting, 9 Breadth-First Search, 10 Depth-First Search (ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes) and Fall 2011 lecture 13 BFS notes (ocw.mit.edu/courses/6-006-introduction-to-algorithms-fall-2011)
  • Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (MIT Press)
  • with the CLRS-based Khan Academy algorithms unit by Thomas Cormen and Devin Balkcom of Dartmouth (khanacademy.org/computing/computer-science/algorithms: binary search, selection sort analysis, merge sort, quicksort overview and analysis)
  • MacTutor History of Mathematics, Al-Khwarizmi (mathshistory.st-andrews.ac.uk/Biographies/Al-Khwarizmi: word algorithm from the Latin title Algoritmi de numero Indorum)
  • D. E. Joyce, Euclid's Elements Book VII Propositions 1 and 2 (mathcs.clarku.edu/~djoyce/elements/bookVII)
  • Wolfram MathWorld, Merge Sort (mathworld.wolfram.com/MergeSort.html: proposed by John von Neumann in 1945, after Knuth 1998 p. 159)
  • Stanford CS "Tony Hoare: Quicksort" (cs.stanford.edu/people/eroberts/courses/soco/projects/2008-09/tony-hoare/quicksort.html: devised while a student at Moscow State University for Russian-English machine translation with a tape dictionary, programmed in Algol 60 and published 1961; the year 1959 from the Wikipedia Quicksort article and its cited sources)
  • Bodleian Libraries, Ada Lovelace (blogs.bodleian.ox.ac.uk/adalovelace: 1843 paper, Note G Bernoulli numbers)
  • Fourmilab text of Menabrea's Sketch with Lovelace's notes (fourmilab.ch/babbage/sketch.html)
  • Seven Bridges of Konigsberg (Euler 1736) and Tower of Hanoi (Edouard Lucas, 1883) checked against the Wikipedia articles and their cited sources.

確認日: 2026-10-17