[Python] シェルソート

Python でシェルソートを実装します。

シェルソート

シェルソート改良挿入ソート英語: Shellsort, Shell sort, Shell’s method)は、in-placeな比較ソートアルゴリズムの一種である。シェルソートは、交換によるソート(バブルソート)あるいは挿入によるソート(挿入ソート)の一般化と見なすことができる[2]。ソートの方法は、まず、間隔の離れた要素の組に対してソートを行い、だんだんと比較する要素間の間隔を小さくしながらソートを繰り返す、というものである。離れた場所の要素からソートを始めることで、単純に近くの要素を比較する場合よりも速く、要素を所定の位置に移動させることができる。ただし、安定ソートではない。

出典: フリー百科事典『ウィキペディア(Wikipedia)』

ちょっとイメージしずらかったのですが、以下の動画で感覚がつかめました。

Sorts 5 Shell Sort

間隔をいくつにするかにより、シェルソートの性能は変わるそうです。

シェルソートと間隔hの決め方【C++】

シェルソートの間隔配列

import random

def shell_sort(array):
    gaps = [7, 3, 1]

    for gap in gaps:
      gap_insertion_sort(array, gap)
      print(f'ギャップ {gap} ソート: {array}')

def gap_insertion_sort(array, gap):
    for i in range(0, len(array), gap):
        current_value = array[i]
        position = i
        while position >= gap and array[position - gap] > current_value:
            array[position] = array[position - gap]
            position = position - gap

        array[position] = current_value


if __name__ == '__main__':

  random.seed(1)
  array = [random.randrange(100) for i in range(20)]
  print('未ソート', array)
  # 未ソート [17, 72, 97, 8, 32, 15, 63, 97, 57, 60, 83, 48, 26, 12, 62, 3, 49, 55, 77, 97]

  shell_sort(array)
  print('ソート済み', array) 
  # ギャップ 7 ソート: [17, 72, 97, 8, 32, 15, 63, 62, 57, 60, 83, 48, 26, 12, 97, 3, 49, 55, 77, 97]
  # ギャップ 3 ソート: [3, 72, 97, 8, 32, 15, 17, 62, 57, 26, 83, 48, 60, 12, 97, 63, 49, 55, 77, 97]
  # ギャップ 1 ソート: [3, 8, 12, 15, 17, 26, 32, 48, 49, 55, 57, 60, 62, 63, 72, 77, 83, 97, 97, 97]
  # ソート済み [3, 8, 12, 15, 17, 26, 32, 48, 49, 55, 57, 60, 62, 63, 72, 77, 83, 97, 97, 97]

想定通りの結果を得ることができました。