C++ での並列配列データ構造

胡金庫 2023年10月12日
C++ での並列配列データ構造

この記事では、C++ で並列配列データ構造を実装する方法を示します。

C++ でカスタム並列配列クラスを実装するために std::vector コンテナを使う

並列配列は、複数のレコードの配列を実装する抽象データ構造であり、各レコードにはエンティティ全体としてアクセスできます。基本的に、対応する要素に並行してアクセスできる複数の同じサイズの配列を想像する必要があります。このデータ構造は、見つかった要素と同じインデックス上の対応する要素にアクセスできるため、配列の 1つが並べ替えられている場合、比較的高速な要素検索操作を提供できます。

並列配列は、さまざまな方法を使用して実装できます。この場合、概念をよりよく説明するための最も簡単なコンテナとして、std::vector STL コンテナを選択しました。

実装を簡素化するために、具象型の 2つの配列(stringint)のみを格納する ParallelArray クラスを定義します。このクラスには、データ構造の内容を格納する std::vector タイプの 2つの private データメンバーが含まれています。内部配列の予想サイズを受け入れ、std::vector::reserved 関数を呼び出して十分なメモリを事前に割り当てるように、単一のコンストラクターが定義されています。このパラメーターはオプションであり、デフォルト値は 20 であることに注意してください。

タイプ ParallelArray のオブジェクトを初期化したら、push_back メンバー関数を使用してデータをオブジェクトにプッシュする必要があります。この関数は、vector メンバー(v1v2)の両方に同じ名前の対応するメンバー関数を呼び出します。また、ParallelArray オブジェクトの現在の要素数を取得するために、size と呼ばれるメンバー関数を定義しました。

このクラスには、構造内に格納されている要素にアクセスするために定義された [] 演算子もあります。ParallelArray には固定データ型の配列があるため、operator[]std::pair<string, int> 値を返します。または、クラステンプレートを作成して、複数のジェネリック型を受け入れ、内部の vector オブジェクトを初期化し、それに応じてメンバー関数を書き換えることもできます。クラスが 3つ以上の内部 vector データメンバーを宣言している場合、operator[] は STL の std::make_tuple メソッドを使用して要素を返すことができます。

#include <iostream>
#include <string>
#include <vector>

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

class ParallelArray {
 public:
  explicit ParallelArray(size_t size = 20) {
    v1.reserve(size);
    v2.reserve(size);
  };

  void push_back(string &d1, int d2);
  size_t size();
  std::pair<string, int> operator[](size_t pos);

 private:
  vector<string> v1;
  vector<int> v2;
};

void ParallelArray::push_back(string &d1, int d2) {
  v1.push_back(d1);
  v2.push_back(d2);
}

std::pair<string, int> ParallelArray::operator[](size_t pos) {
  if (pos <= v1.size()) {
    return std::make_pair(v1[pos], v2[pos]);
  } else {
    return std::make_pair("null", -1);
  }
}

size_t ParallelArray::size() { return v1.size(); }

template <typename T1, typename T2>
void printPair(const std::pair<T1, T2> &pp) {
  cout << "{" << pp.first << "," << pp.second << "}" << endl;
}

int main() {
  ParallelArray pa1;

  vector<string> data_set1 = {"Precise", "Quantal", "Saucy", "Raring"};

  vector<int> data_set2 = {11, 22, 33, 44};

  for (size_t i = 0; i < data_set1.size(); ++i) {
    pa1.push_back(data_set1[i], data_set2[i]);
  }

  for (size_t i = 0; i < pa1.size(); ++i) {
    printPair(pa1[i]);
  }

  return EXIT_SUCCESS;
}

出力:

{Precise,11}
{Quantal,22}
{Saucy,33}
{Raring,44}

どちらのコードスニペットでも、基本的なドライバーコードを main 関数の一部として実装して ParallelArray オブジェクトを作成し、クラスのコンテンツを出力します。printPair ヘルパー関数は、std::pair オブジェクトの値をコンソールに表示するために使用されます。

さらに、pop_back メンバー関数を追加して、各 vector データメンバーの末尾から格納されている要素を削除できます。pop_back 関数はパラメーターを受け入れず、std::vector::pop_back 関数を呼び出します。後者の関数の使用法は、次のコード例に示されています。

#include <iostream>
#include <string>
#include <vector>

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

class ParallelArray {
 public:
  explicit ParallelArray(size_t size = 20) {
    v1.reserve(size);
    v2.reserve(size);
  };

  void push_back(string &d1, int d2);
  void pop_back();
  size_t size();
  std::pair<string, int> operator[](size_t pos);

 private:
  vector<string> v1;
  vector<int> v2;
};

void ParallelArray::push_back(string &d1, int d2) {
  v1.push_back(d1);
  v2.push_back(d2);
}

std::pair<string, int> ParallelArray::operator[](size_t pos) {
  if (pos <= v1.size()) {
    return std::make_pair(v1[pos], v2[pos]);
  } else {
    return std::make_pair("null", -1);
  }
}

size_t ParallelArray::size() { return v1.size(); }

void ParallelArray::pop_back() {
  v1.pop_back();
  v2.pop_back();
}

template <typename T1, typename T2>
void printPair(const std::pair<T1, T2> &pp) {
  cout << "{" << pp.first << "," << pp.second << "}" << endl;
}

int main() {
  ParallelArray pa1;

  vector<string> data_set1 = {"Precise", "Quantal", "Saucy", "Raring"};

  vector<int> data_set2 = {11, 22, 33, 44};

  for (size_t i = 0; i < data_set1.size(); ++i) {
    pa1.push_back(data_set1[i], data_set2[i]);
  }

  for (size_t i = 0; i < pa1.size(); ++i) {
    printPair(pa1[i]);
  }

  pa1.pop_back();
  pa1.pop_back();

  cout << "------------------------" << endl;
  for (size_t i = 0; i < pa1.size(); ++i) {
    printPair(pa1[i]);
  }

  return EXIT_SUCCESS;
}

出力:

{Precise,11}
{Quantal,22}
{Saucy,33}
{Raring,44}
------------------------
{Precise,11}
{Quantal,22}
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

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

LinkedIn Facebook

関連記事 - C++ Array