概要
- ソートのアルゴリズム
- 既に整列してある複数個の列を1個の列にマージする際に、小さいものから先に新しい列に並べれば、新しい列も整列されている、という分割統治法を用いる。
おおまかな流れ
- 分解/結合する
- 2つのリストを並べ替える
ポイント(1)
分解/結合する
ー 要素数が1になるまで分解する ー 分解は要素数/2で分解する ー 奇数の時は(要素数-1)/2
ー 並べ替えつつ結合していく ー 結合する順番は分解とは逆の順序で行う
ポイント(2)
2つのリストを並べ替える
- 新しいソート済みリストを用意
- 2つのリストの先頭同士を比較して小さい方を取り出しソート済みリストに入れる
- どちらかのリストが空になるまで2を繰り返す
- 余っている方のリストをソート済みリストの後ろにくっつける
サンプルコード (Python)
Pythonの場合
import argparse
def merge(left, right):
sorted_list = []
while left and right:
smaller = left if left[0] < right[0] else right
sorted_list.append(smaller.pop(0))
sorted_list.extend(left if left else right)
return sorted_list
def merge_sort(elms):
length = len(elms)
if length <= 1:
return elms
else:
harf = length / 2
sorted_left = merge_sort(elms[:harf])
sorted_right = merge_sort(elms[harf:])
return merge(sorted_left, sorted_right)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-s', dest='sep', default=' ')
parser.add_argument('--int', dest='int_', default=None, action='store_true')
opts = parser.parse_args()
type_ = lambda s: s
if opts.int_:
type_ = int
line = sys.stdin.readline()
elms = map(type_, map(lambda elm: elm.strip(), line.split(opts.sep)))
sorted_list = map(str, merge_sort(elms))
print opts.sep.join(sorted_list)
if __name__ == '__main__':
main()
実行する
$ chmod 744 merge_sort.py
$ echo 4 1 3 5 6 6 1 9 8 2 | ./merge_sort.py --int
1123456689
特徴
- 平均計算量 O(n log n)
- 最悪計算量 O(n log n)
- 配列にランダムアクセスする必要なし
良いところ
- そこそこ速い
速い時と遅い時で計算量があまり違わない
平均計算量: O(n log n)
- 最悪計算量: O(n log n)
- シーケンシャルアクセスしかできないデータ構造にも使える ex. 連結リストなど
悪いところ
- ソート済みリストの領域確保が必要配列長の 1/2 のサイズ
- ランダムアクセスが出来る構造であればクイックソートとかの方が速い