バブルソート(沈み込みソートとも呼ばれる)は、入力リストを要素ごとに繰り返し走査し、現在の要素を次の要素と比較し、必要に応じて値を交換するシンプルなソートアルゴリズムです。このリスト走査は、走査中に値交換が不要になるまで繰り返され、リストが完全にソートされた状態になります。比較ソートの一種であるこのアルゴリズムは、より大きな要素がリストの上位に「泡のように」上がっていく様子から、バブルソートと名付けられました。
実用上は性能が悪く、主に教育ツールとして使用されています。PythonやJavaなどの一般的なプログラミング言語に組み込まれているソートライブラリでは、クイックソート、ティムソート、マージソートなどのより効率的なアルゴリズムが使用されています。[ 2 ] [ 3 ]
バブルソートアルゴリズムの最初の記述は、数学者で保険数理士のエドワード・ハリー・フレンドによる1956年の論文[ 4 ]「電子計算機システム上のソート」[ 5 ]で、Association for Computing Machinery (ACM) Journalの第3巻第3号に「ソート交換アルゴリズム」として掲載された。フレンドはこのアルゴリズムの基本を説明し、当初は彼の論文は注目されなかったが、数年後、ケネス・E・アイバーソンを含む多くのコンピュータ科学者によって再発見され、アイバーソンが現在の名称を考案した。

バブルソートの最悪ケースと平均の複雑さは、 どこは、ソート対象のアイテム数です。ほとんどの実用的なソートアルゴリズムは、最悪の場合または平均的な複雑さが大幅に改善されており、多くの場合、他にも挿入ソートなどのソートアルゴリズムは、一般的にバブルソートよりも高速で、複雑さも変わりません。そのため、バブルソートは実際にはほとんど使用されていません。
挿入ソートと同様に、バブルソートは適応型であり、クイックソートのようなアルゴリズムよりも優位に立つことができます。つまり、平均時間計算量は劣るものの、リストが既にほとんどソートされている(反転が少ない)場合には、これらのアルゴリズムよりも優れたパフォーマンスを発揮する可能性があります。たとえば、バブルソートは既にソートされているリストに対してはクイックソートは依然としてその全機能を実行します。選別プロセス。
どのようなソートアルゴリズムでも作成できますが事前にソートされたリストでは、アルゴリズムを実行する前にリストをチェックするだけでパフォーマンスを向上させることができますが、ほぼソートされたリストでは、その効果を再現するのはより困難です。
バブルソートのパフォーマンスは、要素がソート中に移動しなければならない距離と方向によって決まります。要素は異なる方向に異なる速度で移動するためです。リストの末尾に向かって移動しなければならない要素は、連続したスワップに参加できるため、速く移動できます。たとえば、リストの中で最大の要素はすべてのスワップに勝つため、リストの先頭付近から始まっても最初のパスでソートされた位置に移動します。一方、リストの先頭に向かって移動しなければならない要素は、1回のパスで1ステップより速く移動できないため、先頭に向かって非常にゆっくりと移動します。最小の要素がリストの末尾にある場合、先頭に移動するためのパス。このため、これらのタイプの要素は、イソップ寓話「ウサギとカメ」の登場人物にちなんで、それぞれウサギとカメと名付けられました。
バブルソートの速度を向上させるために、タートルを排除するためのさまざまな試みが行われてきました。カクテルソートは、開始から終了まで進み、その後逆方向に進み、終了から開始まで進む双方向バブルソートです。タートルをかなりうまく移動できますが、最悪の場合の複雑さ。コームソートは大きな間隔で区切られた要素を比較し、リストを滑らかにするために間隔をどんどん小さくしていく前に、タートルを非常に速く移動させることができます。その平均速度は、クイックソートのようなより高速なアルゴリズムに匹敵します。
数値の配列「5 1 4 2 8」をバブルソートを使用して最小値から最大値の順に並べ替えます。各ステップでは、太字で示されている要素が比較されます。3回のパスが必要です。
これで配列は既にソートされていますが、アルゴリズムはそれが完了したかどうかを判断できません。ソートされたことを確認するには、スワップなしでさらに1回全体を走査する必要があります。
擬似コードでは、このアルゴリズムは(0から始まる配列で)次のように表現できます。
procedure bubbleSort ( A :ソート可能なアイテムのリスト) n := length ( A ) repeat swapped := false for i := 1 to n - 1 inclusive do { このペアが順不同の場合 } if A [ i - 1 ] > A [ i ] then { それらを交換して、何かが変更されたことを記憶する } swap ( A [ i - 1 ] , A [ i ]) swapped := true end if end for until not swapped end procedureバブルソートアルゴリズムは、n回目のパスでn番目に大きい要素を見つけて最終位置に配置するという点に着目することで最適化できます。そのため、内側のループでは、 n回目の実行時に最後のn -1個の項目を参照する必要がなくなります。
procedure bubbleSort ( A :ソート可能なアイテムのリスト) n := length ( A ) repeat swapped := false for i := 1 to n - 1 inclusive do if A [ i - 1 ] > A [ i ] then swap ( A [ i - 1 ] , A [ i ]) swapped := true end if end for n := n - 1 until not swapped end procedureより一般的には、1回のパスで複数の要素が最終位置に配置される場合があります。特に、各パスの後、最後のスワップ以降のすべての要素はソートされ、再度チェックする必要はありません。これにより、多くの要素をスキップできるため、最悪の場合の比較回数が約50%改善されます(ただし、スワップ回数は改善されません)。また、新しいコードが変数を包含するため、複雑さはほとんど増えませんswapped。
これを擬似コードで表現すると、次のようになります。
procedure bubbleSort ( A :ソート可能なアイテムのリスト) n := length ( A ) repeat newn := 0 for i := 1 to n - 1 inclusive do if A [ i - 1 ] > A [ i ] then swap ( A [ i - 1 ] , A [ i ]) newn := i end if end for n := newn until n ≤ 1 end procedureカクテルシェーカーソートなどの代替的な改良版は、隣接するアイテムを繰り返し比較して交換するという同じ考え方を維持しながら、バブルソートのパフォーマンスを向上させようとするものです。

バブルソートは理解しやすく実装も容易な最も単純なソートアルゴリズムの一つですが、その計算量はO ( n² )と大きいため、要素数が少ないリストを超えると効率が著しく低下します。単純なO ( n² )のソートアルゴリズムの中でも、挿入ソートのようなアルゴリズムは通常、バブルソートよりもはるかに効率的です。
バブルソートはその単純さから、コンピュータサイエンスの入門学生にアルゴリズム、あるいはソートアルゴリズムの概念を紹介するためによく用いられます。しかし、オーウェン・アストラチャンなどの一部の教育者は、バブルソートとそのコンピュータサイエンス教育における継続的な人気を批判し、もはや教えるべきではないとまで主張しています。[ 6 ]
有名な「ジャーゴンファイル」では、バブルソートを「典型的な、ひねくれたひどいアルゴリズム」と呼んでいるが、バブルソートも「一般的な悪いアルゴリズム」と呼んでいる。[ 7 ]ドナルド・クヌースは『コンピュータプログラミングの技法』の中で、「バブルソートには、キャッチーな名前と、いくつかの興味深い理論的問題につながるという事実以外に、推奨できる点は何もないようだ」と結論付け、そのうちのいくつかを論じている。[ 8 ]
バブルソートは最悪の場合、実行時間において挿入ソートと漸近的に同等ですが、必要なスワップ回数には大きな違いがあります。アストラカンらの実験結果からも、ランダムなリストに対しても挿入ソートの方がはるかに優れたパフォーマンスを発揮することが示されています。こうした理由から、現代のアルゴリズムの教科書の多くは、バブルソートアルゴリズムの使用を避け、挿入ソートを推奨しています。
バブルソートは、最新のCPUハードウェアとの相性も悪い。挿入ソートの少なくとも2倍の書き込み回数、2倍のキャッシュミス、漸近的に多くの分岐予測ミスが発生する。AstrachanによるJavaでの文字列ソートの実験では、バブルソートは挿入ソートの約5分の1の速度、選択ソートの70%の速度であることが示されている。[ 6 ]
コンピュータグラフィックスにおいて、バブルソートは、ほぼソートされた配列内の非常に小さなエラー(例えば、2つの要素の入れ替え)を検出し、線形時間計算量(2 n)で修正できる能力で広く利用されています。例えば、多角形塗りつぶしアルゴリズムでは、境界線が特定の走査線(x軸に平行な線)におけるx座標でソートされ、 yが増加するにつれて、2つの線の交点でのみ順序が変わります(2つの要素が入れ替わります)。バブルソートは、挿入ソートと同様に、安定ソートアルゴリズムです。
バブルソートは時折「シンキングソート」と呼ばれることがある。[ 9 ]
例えば、ドナルド・クヌースは、値を目的の位置またはそれに近い位置に挿入することを「値が適切なレベルに落ち着く」と表現し、「このソート方法は、ふるい分けまたは沈下法と呼ばれることもある」と述べています。[ 10 ]
この議論が長引くのは、このアルゴリズムを2つの異なる、しかしどちらも妥当な視点から容易に検討できるためである。
2007年のインタビューで、元Google CEOのエリック・シュミットは、当時大統領候補だったバラク・オバマに100万個の整数をソートする最良の方法について尋ねた。オバマは少し間を置いて、「バブルソートは間違った方法だと思う」と答えた。[ 11 ] [ 12 ]
{{cite AV media}}: CS1メンテナンス: 場所 (リンク)