マージソート: 小分けにしてから合体しよう
マージソートは、リストを半分ずつ分け、最後に小さい順になるよう合体する方法です。
バラバラにしたカードを、2つの山ごとに「小さいほうから先に出す」と考えると分かりやすいです。
使いどころ
- 大きなデータを安定して速く並べ替えたいとき
- 「分けて考える」再帰の練習をしたいとき
- クイックソートと違う考え方のソートを比べたいとき
手順
- リストを半分に分ける
- 左半分と右半分をそれぞれ並べ替える
- 2つの並んだリストを、小さい順に合体する
- 1つの並んだリストになったら完成
図で見る
コピペ用コード
def merge_sort(numbers):
if len(numbers) <= 1:
return numbers
middle = len(numbers) // 2
left = merge_sort(numbers[:middle])
right = merge_sort(numbers[middle:])
result = []
while left and right:
result.append(left.pop(0) if left[0] < right[0] else right.pop(0))
return result + left + right
print(merge_sort([5, 3, 8, 1, 4]))
コードの読み方
len(numbers) <= 1は、もう分けなくてよい状態です。leftとrightは、それぞれ並び替え済みの小さなリストです。while left and rightで、左と右の先頭を比べて小さいほうを取り出します。
計算量
マージソートは、分ける回数が少なく、合体では全体を1回ずつ見るため、だいたい O(n log n) で動きます。