マージソート
マージソートは、ソートのアルゴリズムで、既に整列してある複数個の列を1個の列にマージする際に、小さいものから先に新しい列に並べれば、新しい列も整列されている、というボトムアップの分割統治法による。大きい列を多数の列に分割し、そのそれぞれをマージする作業は並列化できる。
出典: フリー百科事典『ウィキペディア(Wikipedia)』
クイックソートと同じような分割統治法のソートアルゴリズムです。
リストを2つに分割して、分割されたリストに含まれるデータが1個ならそれを返ます。
リストに含まれるデータが2個以上の時は、そのリストにマージソートを再帰的に適用し、その結果として返ってきたソート済みのリストを、ソートしながら一つのリストにまとめます。
マージソートの時間計算量は、平均、最悪ともに\( O ( N \log N) \)と、 クイックソートは平均 \( O ( N \log N) \) 、最悪 \( O ( N ^2) \)なので、 最悪時間計算量はクイックソートより良いです。
クイックソートと異なり安定ソートですが、内部ソートではありません。
ソートのために\( \Theta (N) \) の追加メモリが必要になります。
連結リストのソートに対しては、クイックソートより適しています。
Java では、順序関係は同じでも内実が異なる可能性のあるオブジェクトのソートには安定ソートであるマージソートを、ソートの安定性が意味のないプリミティブにはクイックソートと使い分けているそうです。
Java: Arrays.sort quicksort and mergesort [duplicate]
Python で実装
マージソートを Python で実装します。
import random def merge_sort(array): if len(array) > 1: # リストを分割 middle_index = len(array) // 2 left_half = array[:middle_index] right_half = array[middle_index:] # 分割したリストを再帰的にソート merge_sort(left_half) merge_sort(right_half) # 返ってきたソート済みのリストを、ソートしながら一つのリストにまとめる。 i = j = k = 0 while i < len(left_half) and j < len(right_half): if left_half[i] < right_half[j]: array[k] = left_half[i] i += 1 else: array[k] = right_half[j] j += 1 k += 1 # まだ残っているものがある場合は処理する。 while i < len(left_half): array[k] = left_half[i] i += 1 k += 1 while j < len(right_half): array[k] = right_half[j] j += 1 k += 1 if __name__ == '__main__': random.seed(1) array = [random.randrange(100) for i in range(10)] print('未ソート', array) # 未ソート [17, 72, 97, 8, 32, 15, 63, 97, 57, 60] merge_sort(array) print('ソート済み', array) # ソート済み [8, 15, 17, 32, 57, 60, 63, 72, 97, 97]