C++ で挿入ソートアルゴリズムを実装する

胡金庫 2023年10月12日
C++ で挿入ソートアルゴリズムを実装する

この記事では、C++ で挿入ソートアルゴリズムを実装する方法を示します。

C++ で std::vector コンテナの挿入ソートを実装する

このガイドでは、std::vector オブジェクトへの参照を取得し、その場でコンテンツを変更する別個の関数として挿入ソートを実装する方法を示します。挿入ソートは、ベクトル内の各要素を繰り返し処理します。現在の要素を前の要素と逆の順序で比較することにより、現在の位置より前のすべての要素が確実にソートされます。

一般に、比較の順序はアルゴリズムのパフォーマンスではそれほど重要ではありませんが、逆の順序を想定し、それに応じてコードを実装します。また、要素を昇順で並べ替えると仮定します。それでも、実際の場合、一般的なソートアルゴリズムは、カスタム比較関数を引数として取ることができるはずです。現在の要素が前の要素よりも小さい場合、比較操作によって要素が右にシフトされることがよくあることに注意してください。後者の操作は、別のネストされた for ループを使用して実装されます。このループは、間違った順序の要素に対して std::swap 関数を呼び出します。

次のコードスニペットには、外側の for ループが配列全体の走査を担当する insertionSort 関数が含まれています。次のステップには前の要素との比較が含まれるため、イテレータをベクトルの 2 番目の要素に初期化します。内側のループは、現在の要素から最初の要素まで反復して比較します。比較関数が true と評価した場合、ペアは交換されます。else 式は、少なくとも 1つの前の要素が現在の要素よりも小さいことが判明したときに、内部ループを強制的に中断することに注意してください。

#include <algorithm>
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

template <typename T>
void printVector(const vector<T> &vec) {
  for (auto &i : vec) {
    cout << i << "; ";
  }
  cout << endl;
}

template <typename T>
void insertionSort(vector<T> &vec) {
  for (auto it = vec.begin() + 1; it != vec.end(); ++it) {
    auto key = it;

    for (auto i = it - 1; i >= vec.begin(); --i) {
      if (*i > *key) {
        std::swap(*i, *key);
        key--;
      } else {
        break;
      }
    }
  }
}

int main() {
  vector<int> vec1 = {43, 5, 123, 94, 359, -23, 2, -1};

  printVector(vec1);
  insertionSort(vec1);
  printVector(vec1);

  return EXIT_SUCCESS;
}

出力:

43; 5; 123; 94; 359; -23; 2; -1;
-23; -1; 2; 5; 43; 94; 123; 359;

あるいは、while ループ構造を使用して insertionSort 関数を再実装することもできます。後者がユーザーにとってより読みやすい形式として好まれる場合です。2つのアルゴリズムは同様の実装ロジックに従い、どちらも std::swap 関数を使用して要素をシフトします。挿入ソートは、大規模なデータセットでは非常に非効率的なアルゴリズムであり、その平均パフォーマンスは O(n2)です。

挿入ソートは、選択ソートと呼ばれる別の 2 次アルゴリズムに似ています。それらは両方ともベクトルを反復処理します。n の反復後、最初の n 要素がソートされます。ただし、選択ソートは、挿入ソートとは対照的に、現在の位置から前方要素を評価します。

#include <algorithm>
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

template <typename T>
void printVector(const vector<T> &vec) {
  for (auto &i : vec) {
    cout << i << "; ";
  }
  cout << endl;
}

template <typename T>
void insertionSort2(vector<T> &vec) {
  auto iter = vec.begin() + 1;
  while (iter != vec.end()) {
    auto key = iter;
    auto it = iter - 1;

    while (it >= vec.begin() && *it > *key) {
      std::swap(*it, *key);
      key--;
      it--;
    }
    iter++;
  }
}

int main() {
  vector<int> vec1 = {43, 5, 123, 94, 359, -23, 2, -1};

  printVector(vec1);
  insertionSort2(vec1);
  printVector(vec1);

  return EXIT_SUCCESS;
}

出力:

43; 5; 123; 94; 359; -23; 2; -1; 
-23; -1; 2; 5; 43; 94; 123; 359; 

挿入ソートは、現在の要素を先行するすべての要素と常に比較する必要がないため、他の O(n2)アルゴリズムと比較して実際にはより効率的です。一方、選択ソートでは、ソートされていないサブ配列内のすべての要素を常に検索して、最小(または最大)の要素を見つける必要があります。後者のクラスは比較演算子のオーバーロードを実装するため、std::string のベクトルで両方の insertionSort 関数の実装を利用できることに注意してください。次の例は、文字列ベクトルを使用した基本的な使用法を示し、ソートされた単語のリストを出力します。

#include <algorithm>
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

template <typename T>
void printVector(const vector<T> &vec) {
  for (auto &i : vec) {
    cout << i << "; ";
  }
  cout << endl;
}

template <typename T>
void insertionSort(vector<T> &vec) {
  auto iter = vec.begin() + 1;
  while (iter != vec.end()) {
    auto key = iter;
    auto it = iter - 1;

    while (it >= vec.begin() && *it > *key) {
      std::swap(*it, *key);
      key--;
      it--;
    }
    iter++;
  }
}

int main() {
  vector<string> vec2 = {"highway", "song",  "work",
                         "borland", "death", "woman"};

  printVector(vec2);
  insertionSort(vec2);
  printVector(vec2);

  return EXIT_SUCCESS;
}

出力:

highway; song; work; borland; death; woman;
borland; death; highway; song; woman; work;
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook

関連記事 - C++ Algorithm