プログラミング
 Computer >> コンピューター >  >> プログラミング >> プログラミング

挿入ソートとは?仕組み・計算量・C++実装例をわかりやすく解説


挿入ソートは、トランプの手札を並べ替えるときの操作によく似た整列アルゴリズムです。カードゲームで手札を昇順に整理する場面を思い浮かべてください。新しいカードを引いたら、すでに並んでいるカードの中から適切な位置を見つけて、そこに差し込みますよね。まさにこれが挿入ソートの基本的な考え方です。

具体的には、データ集合から1つの要素を取り出し(この値を「キー」と呼びます)、そのキーを挿入できる隙間を作るために、左側にあるより大きい要素を順番に右へずらしていきます。そして、正しい位置が見つかったところでキーを挿入します。これを配列の末尾まで繰り返すことで、全体が昇順に整列されていきます。

挿入ソートの計算量

  • 時間計算量:最良ケース O(n)、平均ケース・最悪ケース O(n²)
  • 空間計算量:O(1)

すでにほぼ整列されたデータに対しては非常に高速に動作する一方、逆順に並んだデータなどでは処理時間が増加します。また、同じ値同士の順序が入れ替わらない「安定なソート」である点も特徴です。

入力と出力

Input:
ソート対象のリスト: 9 45 23 71 80 55
Output:
ソート前の配列: 9 45 23 71 80 55
ソート後の配列: 9 23 45 55 71 80

アルゴリズム

insertionSort(array, size)

入力 − データを格納した配列と、その要素数

出力 − 昇順にソートされた配列

Begin
    for i := 1 to size-1 do
        key := array[i]
        j := i
        while j > 0 AND array[j-1] > key do
            array[j] := array[j-1]
            j := j – 1
        done
        array[j] := key
    done
End

アルゴリズムのポイント

先頭の要素は「整列済み」とみなし、2番目の要素(インデックス1)から順にキーとして取り出します。キーを左側の整列済み領域と比較しながら、キーより大きい要素を1つずつ右へシフトし、シフトが止まった位置にキーを挿入します。こうすることで、左側の領域は常に整列された状態が保たれます。

C++による実装例

#include<iostream>
using namespace std;

void display(int *array, int size) {
    for(int i = 0; i<size; i++)
        cout << array[i] << " ";
    cout << endl;
}

void insertionSort(int *array, int size) {
    int key, j;

    for(int i = 1; i<size; i++) {
        key = array[i];  // 値を取り出す
        j = i;

        while(j > 0 && array[j-1] > key) {
            array[j] = array[j-1];  // 大きい要素を右へずらす
            j--;
        }

        array[j] = key;  // 適切な位置に挿入
    }
}

int main() {
    int n;
    cout << "Enter the number of elements: ";
    cin >> n;
    int arr[n];  // 指定された要素数で配列を作成
    cout << "Enter elements:" << endl;

    for(int i = 0; i<n; i++) {
        cin >> arr[i];
    }

    cout << "Array before Sorting: ";
    display(arr, n);
    insertionSort(arr, n);
    cout << "Array after Sorting: ";
    display(arr, n);
}

実行結果

Enter the number of elements: 6
Enter elements:
9 45 23 71 80 55
Array before Sorting: 9 45 23 71 80 55
Array after Sorting: 9 23 45 55 71 80

ソートの過程(イメージ)

[9] 45 23 71 80 55   ← 先頭は整列済みとみなす
[9 45] 23 71 80 55   ← 45はそのまま挿入
[9 23 45] 71 80 55   ← 23を9と45の間に挿入
[9 23 45 71] 80 55   ← 71はそのまま挿入
[9 23 45 71 80] 55   ← 80はそのまま挿入
[9 23 45 55 71 80]   ← 55を適切な位置に挿入して完成

  1. Pythonで学ぶ挿入ソート(Insertion Sort)の仕組みと実装方法

    この記事では、Python 3.xにおける挿入ソート(Insertion Sort)の基本的な考え方と、実際のコードによる実装方法をわかりやすく解説します。 挿入ソートのアルゴリズム 挿入ソートは、配列を「整列済みの部分」と「未整列の部分」に分け、未整列の要素を一つずつ取り出して、整列済み部分の正しい位置に挿入していくシンプルなソート手法です。処理の手順は以下の通りです。 1. 各反復ごとに整列済みの配列を少しずつ拡大しながら、入力要素を走査する。 2. 現在の要素(キー)を、整列済み配列内の最大値と比較する。 3. キーがその最大値より大きければ、要素はそのままの位置に置かれ、 次の要

  2. Rubyで学ぶ挿入ソート:仕組みから計算量まで徹底解説

    ※本記事は、Rubyでさまざまなソートアルゴリズムを実装するシリーズの第4回です。第1回ではバブルソート、第2回では選択ソート、第3回ではマージソートを取り上げました。データのソート手法をさまざまな角度から探っていくシリーズもいよいよ折り返し地点。今回は挿入ソート(Insertion Sort)に焦点を当てます。挿入ソートには魅力的な特徴がたくさんあります。まず、挿入ソートは安定(stable)なアルゴリズムです。つまり、同じキーを持つ要素同士の相対的な順序が入れ替わることがありません。また、インプレース(in-place)アルゴリズムでもあるため、ソート結果を保存するための新しい配列を作成す