配列内の数値を整列させる_3(挿入法)

配列内の数値を、昇順(降順)に整列してみます。
反復(繰り返し)処理のネスト(入れ子)処理の
基礎として配列内数値の整列がよく説明されています。
この基本的な整列法として、選択法、隣接交換法、挿入法が
あります。

挿入法の簡単な解説とプログラムしてみます。
※この説明では、昇順にすることが前提です。

1.最初は、配列要素全体が未整列要素です。
 この先頭要素を整列確定要素とします。
2.確定要素の末尾の次の要素(未整列要素の先頭)を
 確定要素の末尾から先頭に向かって順に比較します。
3.比較結果が、確定要素 > 未整列の先頭要素
 の間は、その前の確定要素へと比較を進めます。
4.比較結果が、確定要素 < 未整列の先頭要素
 となった位置の1つ後方の位置が、未整列先頭要素の
 適切な挿入位置となります。
5.位置が確定し挿入する場合、その位置に空き
 領域を用意する必要があります。
 空き領域の確保には、挿入位置から整列済み
 末尾までの要素の値を、1要素分後ろにずらします。
 ※この1要素分をずらす方法として、
  ・3.の比較時に比較しながら後ろにずらす。
  ・4.の挿入位置が確定した時点でまとめてずらす。
  のどちらかになります。
6.確保できた空き領域に、未整列の先頭要素を
 写します。
7.比較に使用した未整列の先頭要素の位置までを
 整列確定要素とし、2.の操作から処理を繰り返します。
8.未整列要素が無くなった(配列要素の末尾まで
 整列済みとなった)時点で整列操作は完了です。

この解説を図にしてみました。
 ※この図では、比較時に後方へずらす処理を行っています。

挿入法(整列)図1
挿入法(整列)図1
挿入法(整列)図2
挿入法(整列)図2
挿入法(整列)図3
挿入法(整列)図3

では、整列_挿入法をプログラムしてみます。

・プロジェクトを作成します。
 Visual Studio 2022を起動し、
 新しいプロジェクトを作成します。
 ・プロジェクトタイプ:"コンソールアプリ"
 ・プロジェクト名:"ct_107_3"
 とします。

ロジェクトの作成1
プロジェクトの作成1
ロジェクトの作成2
ロジェクトの作成2
ロジェクトの作成3
ロジェクトの作成3

・プログラム記述・編集画面が表示されるので、
 以下のプログラムを記述します。

プログラム記述前の記述編集画面
プログラム記述前の記述編集画面
プログラム記述後の記述編集画面
プログラム記述後の記述編集画面

 プログラムの記述内容

// 配列内の数値を整列させる
// 挿入法による昇順(降順)

#include <iostream>

int main()
{
    // 変数宣言と初期化
    int array[] = { 5,1,7,6,4,8,2,10,3,9 };
    int num;
    int work;
    int index;

    // array配列の要素数を取得
    num = sizeof(array) / sizeof(array[0]);

    // 整列前の配列内数値の表示
    printf("整列前 :");
    for (int i = 0; i < num; i++) {
        printf("%4d", array[i]);
    }
    printf("\n");

    // その値の正規位置を探しながらの入替ループ
    for (int head = 1; head < num; head++) {
        work = array[head];
        for (index = head - 1; index >= 0 && array[index] > work; index--) {
            array[index + 1] = array[index];
        }
        array[index + 1] = work;
    }

    // 整列後の配列内数値の表示
    printf("整列後 :");
    for (int i = 0; i < num; i++) {
        printf("%4d", array[i]);
    }
    printf("\n");

    return EXIT_SUCCESS;
}

 簡単なプログラム解説です。

  このプログラムでは、比較し挿入位置とは違う場合、
  後方へ値を移しながら比較を進めるプログラム例です。
  ※挿入位置確定後に、まとめて整列要素を後方へ移す
   プログラム例ではありません。

  ・変数宣言と初期化
   int array[] = { 5,1,7,6,4,8,2,10,3,9 };
    整列に使用する未整列値の配列を宣言します。
   int num;
    配列の要素数を格納するための変数
   int work;
    未整列の先頭要素(未整列側の比較対象要素)の仮置き用変数

    ※後方へずらす場合に、この要素位置を使用するためです。
   int index;
    確定済み配列要素の比較位置を格納するための変数

  ・array配列の要素数を取得
   num = sizeof(array) / sizeof(array[0]);
    この式によって、配列内の要素数を取得できます。

  ・整列前の配列内数値の表示
   printf("整列前 :");
   for (int i = 0; i < num; i++) {
     printf("%4d", array[i]);
   }
   printf("\n");
    整列前の要素の値を表示するためのループ処理

  ・その値の正規位置を探しながらの入替ループ
   for (int head = 1; head < num; head++) {
    未整列配列の比較対象位置を1つずつ後方へずらしながらのループ

     work = array[head];
      未整列の先頭要素(整列させる)値を仮置きします。

     for (index = head - 1; index >= 0 && array[index] > work; index--) {
      整列済み配列を末尾から先頭に向かって比較するループ

       array[index + 1] = array[index];
        比較した結果、確定要素の比較対象 > 未整列要素の比較対象の場合、
        その確定要素側の比較対象要素の値を1つ後方へずらします。
        ※最初の比較での後方位置は、未整列配列の先頭位置となります。

     }
     array[index + 1] = work;
      比較した結果、確定要素の比較対象 < 未整列要素の比較対象の場合、
      その未整列要素側の比較対象要素の値を1つ後方位置に複写します。
      ※この複写位置は、元の値は後方に移されているので、空き領域となっています。

   }

  ・整列後の配列内数値の表示
   printf("整列後 :");
   for (int i = 0; i < num; i++) {
     printf("%4d", array[i]);
   }
   printf("\n");
    整列後の要素の値を表示するためのループ処理

・実行してみます。
 上段メニュー"デバッグ(D)"のサブメニューより、
 "デバッグなしで開始(H)"を選択します。

ビルド、実行指示画面
ビルド、実行指示画面

・実行結果は、デバッグコンソール画面が開き表示されます。
 ※この実行では、整列前の配列内の値と、
  整列後の配列内の値を表示しています。
 ※この画面は、何かのキーを打鍵することで閉じることができます。

実行結果、デバッグコンソール画面
実行結果、デバッグコンソール画面