Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

クイックソート

クイックソート(quick sort) は分割統治法を使うソートアルゴリズム。ピボット(基準値)を選び、ピボットより小さい要素と大きい要素に分割して再帰的にソートする。平均的に最速のソートアルゴリズムの一つ。

計算量
最悪時間計算量O(n2)O(n^2)(ピボット選択が偏る場合)
平均時間計算量O(nlog⁡n)O(n \log n)
最良時間計算量O(nlog⁡n)O(n \log n)
空間計算量O(log⁡n)O(\log n)(再帰スタック)

特徴

  • 非安定ソート(実装による)

  • in-place(補助配列不要)

  • 定数係数が小さく、キャッシュ効率が良いため実用上高速

  • ピボット選択がパフォーマンスの鍵

アルゴリズム

quick_sort(arr, lo, hi):
    if lo >= hi: return
    p = partition(arr, lo, hi)  # ピボットの最終位置を返す
    quick_sort(arr, lo, p - 1)
    quick_sort(arr, p + 1, hi)

Lomuto分割法: 末尾をピボットにし、左から走査する。シンプルだが定数係数が若干大きい。

Hoare分割法: 両端から走査。実際には交換回数が少なく速い。

in-place 実装(Lomuto 分割法)

最悪ケース(ナイーブ実装での注意)

常に最大・最小をピボットに選ぶと、分割が n−1n-1 と 0 になり O(n2)O(n^2) に退化する。例えば既ソート済み配列に末尾ピボットを適用した場合が該当する。

対策:

  • ランダムピボット: random.choice でピボットを選ぶ

  • Median-of-3: 先頭・中央・末尾の中央値をピボットに(上記の _partition 参照)

  • イントロソート: 再帰深度が log⁡n\log n を超えたらヒープソートに切り替える(C++ STL の std::sort)