C++ の std::merge アルゴリズム

胡金庫 2023年10月12日
  1. C++ で std::merge アルゴリズムを使用して 2つのソートされた範囲のコンテンツをマージする
  2. C++ で std::set_union アルゴリズムを使用して 2つのソートされた範囲のコンテンツをマージする
C++ の std::merge アルゴリズム

この記事では、C++ で std::merge STL アルゴリズムを使用する方法について説明します。

C++ で std::merge アルゴリズムを使用して 2つのソートされた範囲のコンテンツをマージする

std::merge 関数は、STL アルゴリズムヘッダー-<algorithm> の下にあります。以前にソートされた 2つの範囲をマージするために利用できます。範囲イテレータは、LegacyInputIterator 要件を満たす必要があります。

次のサンプルコードでは、ランダムな整数値を持つ 2つの vector コンテナを作成し、std::merge アルゴリズムを使用してそれらを 3 番目のベクトルにマージします。マージする前に、v1 および v2 コンテナで std::sort アルゴリズムを呼び出します。ランダム整数は、高品質のランダム性のために推奨される方法である STL 機能を使用して生成されます。また、値をベクトルに格納するために、通常のループの代わりにラムダ式を使用した std::generate アルゴリズムを使用します。

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <random>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

template <typename T>
void printRange(std::vector<T> v) {
  for (const auto &item : v) {
    cout << std::setw(2) << item << ", ";
  }
  cout << endl;
}

int main() {
  std::random_device rd;
  std::mt19937 mt(rd());
  std::uniform_int_distribution<> dis(0, 10);

  std::vector<int> v1(5), v2(5);
  std::generate(v1.begin(), v1.end(), [&dis, &mt] { return dis(mt); });
  std::generate(v2.begin(), v2.end(), [&dis, &mt] { return dis(mt); });

  std::sort(v1.begin(), v1.end());
  std::sort(v2.begin(), v2.end());

  cout << "v1: ";
  printRange(v1);
  cout << "v2: ";
  printRange(v2);

  std::vector<int> v3(v1.size() + v2.size());
  std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());

  cout << "v3: ";
  printRange(v3);

  return EXIT_SUCCESS;
}

出力:

v1:  2,  2,  4,  9, 10,
v2:  0,  2,  4,  4,  9,
v3:  0,  2,  2,  2,  4,  4,  4,  9,  9, 10,

前のコードは、宛先ベクトルをベクトルサイズの合計で初期化して、v1v2 の内容を格納できるようにします。または、アルゴリズムの 5 番目のパラメーターとして std::back_inserter を使用して、ベクトルを動的に拡張することもできます。std::merge アルゴリズムが使用されている場合、これら 2つの方法の間に機能的な違いはありませんが、他の同様のアルゴリズムには特定のバージョンが必要な場合があります。

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <random>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

template <typename T>
void printRange(std::vector<T> v) {
  for (const auto &item : v) {
    cout << std::setw(2) << item << ", ";
  }
  cout << endl;
}

int main() {
  std::random_device rd;
  std::mt19937 mt(rd());
  std::uniform_int_distribution<> dis(0, 10);

  std::vector<int> v1(5), v2(5);
  std::generate(v1.begin(), v1.end(), [&dis, &mt] { return dis(mt); });
  std::generate(v2.begin(), v2.end(), [&dis, &mt] { return dis(mt); });

  std::sort(v1.begin(), v1.end());
  std::sort(v2.begin(), v2.end());

  cout << "v1: ";
  printRange(v1);
  cout << "v2: ";
  printRange(v2);

  std::vector<int> v3;
  std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(),
             std::back_inserter(v3));

  cout << "v3: ";
  printRange(v3);

  return EXIT_SUCCESS;
}
v1:  2,  2,  4,  9, 10,
v2:  0,  2,  4,  4,  9,
v3:  0,  2,  2,  2,  4,  4,  4,  9,  9, 10,

C++ で std::set_union アルゴリズムを使用して 2つのソートされた範囲のコンテンツをマージする

std::merge は、正確に std::distance(first1, last1) + std::distance(first2, last2) の要素数を含む出力範囲を構築します。ただし、同様の機能を持つ std::set_union アルゴリズムは、要素が両方の範囲で見つかったかどうかをチェックし、見つかった場合は、すべての要素インスタンスが最初の範囲からコピーされますが、std::max(n-m, 0)2 番目の範囲のインスタンス。ここで、m は最初の範囲のインスタンスの数、n は 2 番目の範囲のインスタンスの数です。

次の例は、std::set_union アルゴリズムを使用した同じコードスニペットを示しています。

#include <iostream>
#include <algorithm>
#include <vector>
#include <random>
#include <iomanip>

using std::cout; using std::cin;
using std::endl; using std::vector;

template<typename T>
void printRange(std::vector<T> v) {
    for (const auto &item : v) {
        cout << std::setw(2) << item << ", ";
    }
    cout << endl;
}

int main() {
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<> dis(0, 10);

    std::vector<int> v1(5), v2(5);
    std::generate(v1.begin(), v1.end(), [&dis, &mt] { return dis(mt); });
    std::generate(v2.begin(), v2.end(), [&dis, &mt] { return dis(mt); });

    std::sort(v1.begin(), v1.end());
    std::sort(v2.begin(), v2.end());

    cout << "v1: ";
    printRange(v1);
    cout << "v2: ";
    printRange(v2);


    std::vector<int> v4;
    std::set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v4));
    cout << "v4: ";
    printRange(v4);

    return EXIT_SUCCESS;
}
v1:  2,  2,  4,  9, 10,
v2:  0,  2,  4,  4,  9,
v4:  0,  2,  2,  4,  4,  9, 10,
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

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

LinkedIn Facebook

関連記事 - C++ Algorithm