マージソート — 分割統治法アプローチ
マージソートの分割統治法戦略を理解します。分割、ソート、マージで保証されたO(n log n)の性能を実現。マージ手順とその安定性を学びます。
Divide and Conquer
詳細な説明
マージソートの動作原理
マージソートは、すべてのケース(最良、平均、最悪)でO(n log n)の時間計算量を達成する古典的な分割統治法アルゴリズムです。配列を再帰的に半分に分割し、各半分をソートし、ソートされた半分をマージして元に戻します。
3つのステップ
- 分割: 配列を2つの半分に分割
- 統治: 各半分を再帰的にソート
- 結合: 2つのソート済み半分を1つのソート済み配列にマージ
function mergeSort(arr, left, right):
if left >= right: return
mid = (left + right) / 2
mergeSort(arr, left, mid)
mergeSort(arr, mid + 1, right)
merge(arr, left, mid, right)
マージ手順
マージステップはアルゴリズムの核心です。2つのソート済みサブ配列を取り、各サブ配列から要素を1つずつ比較しながら1つのソート済み配列に結合します:
function merge(arr, left, mid, right):
一時配列を作成 L = arr[left..mid], R = arr[mid+1..right]
i = 0, j = 0, k = left
while i < len(L) and j < len(R):
if L[i] <= R[j]:
arr[k] = L[i]; i++
else:
arr[k] = R[j]; j++
k++
残りの要素をコピー
再帰ツリー
8要素の配列では、再帰ツリーは3レベル(log₂ 8 = 3)です。各レベルですべてのn要素がマージ中に処理されるため、総作業量はn * log nになります。
保証されたO(n log n)
クイックソートとは異なり、マージソートの性能は入力順序に依存しません。分割は常に正確な半分(ピボット選択に依存しない)で行われるため、再帰深度は常にlog nで、各レベルはO(n)の作業を行います。
トレードオフ:空間
マージソートの主な欠点は、マージ中に使用される一時配列のO(n)の追加空間要件です。メモリ制約のある環境には適しません。
ユースケース
マージソートは、入力順序に関係なく保証されたO(n log n)性能が必要な場合に最適なアルゴリズムです。データを順次アクセスするため、ディスクI/Oに効率的な外部ソート(メモリに収まらないデータのソート)に使用されます。また、安定性が重要なオブジェクトのソートにPythonとJavaで使用されるTimsortの基盤でもあります。