LoginSignup
0
0

More than 3 years have passed since last update.

Pythonでソートアルゴリズムの再発明をしてみる: 挿入ソート

Posted at

概要

  • Pythonでソートアルゴリズムを再発明してみるだけ
  • 今回は挿入ソートについて
  • 参考サイトのサンプルコードをできるだけ見ずに実装する
  • とりあえず昇順ソートのみの対応とする

挿入ソートの概要

  • ソート済みの配列の中の適切な位置に未ソートの要素を挿入することを繰り返すアルゴリズム
  • シンプルで実装が容易である一方、基本的に遅い
  • 遅いけどバブルソートよりはマシ
    • 要素を挿入する処理について、挿入箇所が見つかればそこでループが終わる
    • ほぼソート済みの配列を処理する場合は速い
  • 安定ソート

基本的な手順

  1. 左端の要素を「ソート済み」とみなす
  2. 左端の次の要素を「未ソート」とみなす
  3. ソート済み要素(の右端)と未ソート要素を比較し、大小関係が逆なら、未ソート要素をソート済み要素の中の適切な位置に挿入して「ソート済み」要素とする。大小関係が合っていれば、その位置のまま「ソート済み」要素とする
  4. 比較する要素両方を1つ右にずらしながら手順3を繰り返す。
  5. 右端まで処理が終わったらソート完了

ソース

import random

def insertion_sort(lst):
    # 配列走査するループ
    # 左端は「ソート済み」なので1から開始
    # 「ソート済み」といってもコード上ではその概念は登場せず、ループカウンタのある時点の値より前がソート済みということになる
    for i in range(1, len(lst)):
        # ソート済み要素の右端(つまりソート済み要素の中での最大値)と、未ソート要素の左端の大小関係比較
        # ループカウンタiの現在の値は未ソート要素、i-1はソート済み要素の右端を指す
        # 未ソート要素のほうが小さい場合は、未ソート要素をソート済み要素の中に挿入しないといけない
        if lst[i-1] > lst[i]:
            # 挿入箇所を探すためのループ
            # ソート済み要素の左端から見ていって、未ソート要素のほうが小さくなる最初の位置に挿入すればいい
            for j in range(0, i):
                if lst[j] > lst[i]:
                    # Pythonにはinsertメソッドがあるので便利
                    # そのような機能がない言語の場合は、挿入箇所以降を全部後ろにずらす処理が必要になる
                    lst.insert(j, lst[i])
                    # insertメソッドの機能は移動ではなく新規追加なので、元の要素を消す必要がある
                    # insertメソッドで要素が一つ増えているため、iではなくi+1が元の要素の位置
                    del lst[i+1]
                    break


lst = list(range(10))
random.shuffle(lst)

print("ソート前: " + str(lst))

insertion_sort(lst)

print("ソート後: " + str(lst))

参考サイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0