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

C言語でpthreadを使ったマルチスレッド二分探索の実装方法

二分探索(バイナリサーチ)は、ソート済みのデータ列に対して最も適しており、効率的な探索アルゴリズムの一つとして知られています。仕組みは非常にシンプルで、まず配列の中央にある要素を調べ、そこからリストを2つに分割します。そして、目的のキーとの大小関係に応じて、左側の部分リストか右側の部分リストのどちらか一方だけを探索対象として絞り込んでいくのです。

基本的なアルゴリズムはすでに理解している前提で、今回は二分探索をマルチスレッド環境で実装する方法を見ていきましょう。生成するスレッド数は、システムに搭載されているCPUコアの数に依存します。以下のコードで具体的なイメージをつかんでください。

サンプルコード

#include <iostream>
#define MAX 16
#define MAX_THREAD 4
using namespace std;
// 配列・キー・その他の変数は、複数スレッドからアクセスできるようグローバルに配置
int arr[] = { 1, 6, 8, 11, 13, 14, 15, 19, 21, 23, 26, 28, 31, 65, 108, 220 };
int key = 31;
bool found = false;
int part = 0;
void* binary_search(void* arg) {
   // スレッドは4つあり、それぞれ配列の1/4ずつを担当する
   int thread_part = part++;
   int mid;
   int start = thread_part * (MAX / 4); // 担当範囲から開始位置と終了位置を設定
   int end = (thread_part + 1) * (MAX / 4);
   // low < high の間、またはキーが見つかるまで探索を続ける
   while (start < end && !found) { // 他のスレッドが要素を発見したら停止する
      mid = (end - start) / 2 + start;
      if (arr[mid] == key) {
         found = true;
         break;
      }
      else if (arr[mid] > key)
         end = mid - 1;
      else
         start = mid + 1;
   }
}
main() {
   pthread_t threads[MAX_THREAD];
   for (int i = 0; i < MAX_THREAD; i++)
      pthread_create(&threads[i], NULL, binary_search, (void*)NULL);
   for (int i = 0; i < MAX_THREAD; i++)
      pthread_join(threads[i], NULL); // メインスレッドとの合流を待機
   if (found)
      cout << key << " found in array" << endl;
   else
      cout << key << " not found in array" << endl;
}

実行結果

31 found in array

コードのポイント

このプログラムでは、16個の要素を持つソート済み配列を4つのスレッドに均等に分割し、各スレッドが担当範囲内で独立して二分探索を行います。グローバル変数 found を共有することで、あるスレッドがキーを発見した時点で他のスレッドも探索を打ち切れるように設計されています。

なお、pthreadライブラリを使用するため、コンパイル時には -lpthread オプションを付ける必要があります(例:g++ sample.cpp -lpthread)。また、実際の環境では partfound への同時アクセスを考慮し、必要に応じてミューテックスやアトミック操作による同期を検討するとより安全です。

  1. C++プログラムにおける二分探索(バイナリサーチ)の基本と実装

    二分探索(バイナリサーチ)とは二分探索は「半区間探索」「対数探索」「バイナリチョップ」とも呼ばれる検索アルゴリズムで、ソート済みの配列の中から目的の値が存在する位置を効率的に見つけ出します。基本的な仕組みは非常にシンプルです。まず、探したい値(ターゲット値)を配列の中央の要素と比較します。一致しなかった場合は、ターゲット値が存在し得ない半分を丸ごと排除し、残りの半分に対して同様の比較を繰り返します。この「中央との比較」と「範囲の絞り込み」を続け、ターゲット値が見つかるか、検索範囲が空になる(=配列にその値が存在しない)かのどちらかで処理が終了します。アイデア自体は簡単ですが、正しく実装するには

  2. C#で二分探索(バイナリサーチ)を実装する方法|仕組みと計算量を解説

    二分探索とは二分探索(バイナリサーチ)は、ソート済みの配列を対象とした高速な検索アルゴリズムです。探索したい値を配列の中央にある要素と比較し、一致しなかった場合は、その値が存在し得ない側の半分の領域を丸ごと除外します。この操作を残りの半分に対して繰り返すことで、効率よく目的の値を見つけ出します。例えば、下図のような配列から「62」という値を探す場合を考えてみましょう。中央の要素との比較結果から、62が存在するのは右側の領域だけであることが分かるため、左半分は完全に除外され、以降は右半分のみが探索対象となります。二分探索の計算量二分探索における各ケースの計算量は以下の通りです。最悪時間計算量O(