📜  使用 pthread 进行二分查找(1)

📅  最后修改于: 2023-12-03 15:22:15.732000             🧑  作者: Mango

使用 pthread 进行二分查找

二分查找是一种常见的算法,利用它可以快速地在有序数组中查找指定元素。在本文中,我们将介绍如何使用 pthread 进行二分查找。

什么是 pthread?

pthread 是 POSIX 标准中线程的 API,其全称为“POSIX threads”。它提供了一些函数,允许可以在一个程序内并发运行多个并发执行线程,而这些线程共享一些数据,同时又拥有各自的私有数据。

如何使用 pthread 进行二分查找?

使用 pthread 进行二分查找的过程,大致可以分为以下几个步骤:

  1. 创建线程
  2. 将数组分为若干部分,每个线程负责一个子数组
  3. 启动每个线程,进行查找
  4. 等待所有线程完成查找,并将结果合并

下面是一个使用 pthread 进行二分查找的示例代码:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define THREAD_NUM 4

int array[] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};

int thread_result[THREAD_NUM];
pthread_mutex_t lock;

void* binarySearch(void* arg){

    int* input = (int*)arg;

    int left = input[0];
    int right = input[1];
    int target = input[2];
    int thread_num = input[3];

    int mid;

    while (left <= right) {
        mid = (left + right) / 2;
        if (array[mid] == target) {
            pthread_mutex_lock(&lock);
            thread_result[thread_num] = mid;
            pthread_mutex_unlock(&lock);
            return NULL;
        } else if (array[mid] > target) {
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }

    return NULL;

}

int main(int argc, char* argv[]){

    int target = atoi(argv[1]);

    pthread_mutex_init(&lock, NULL);

    int part_size = sizeof(array) / sizeof(int) / THREAD_NUM;
    pthread_t threads[THREAD_NUM];
    int inputs[THREAD_NUM][4];

    for (int i = 0; i < THREAD_NUM; i++){
        int left = i * part_size;
        int right = (i == THREAD_NUM - 1) ? sizeof(array) / sizeof(int) - 1 : left + part_size - 1;
        inputs[i][0] = left;
        inputs[i][1] = right;
        inputs[i][2] = target;
        inputs[i][3] = i;
        pthread_create(&threads[i], NULL, binarySearch, inputs[i]);
    }

    for (int i = 0; i < THREAD_NUM; i++) {
        pthread_join(threads[i], NULL);
    }

    int result = -1;
    for (int i = 0; i < THREAD_NUM; i++) {
        if (thread_result[i] != -1) {
            result = thread_result[i];
            break;
        }
    }

    if (result != -1) {
        printf("Target found at index %d\n", result);
    } else {
        printf("Target not found\n");
    }

    pthread_mutex_destroy(&lock);

    return 0;
}

代码说明
  1. 首先定义了一个静态数组 array,其中存储了 10 个有序的整数。
int array[] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
  1. 定义了一个 thread_result 数组,用于存储每个线程查找的结果。定义了一个 pthread_mutex_t 锁变量 lock,用于在多个线程之间进行同步。
int thread_result[THREAD_NUM];
pthread_mutex_t lock;
  1. 定义了一个 binarySearch 函数,用于进行二分查找。该函数需要传入一个包含 4 个整数的数组 input,这些整数分别表示左边界、右边界、查找目标和线程编号。
void* binarySearch(void* arg){

    int* input = (int*)arg;

    int left = input[0];
    int right = input[1];
    int target = input[2];
    int thread_num = input[3];

    int mid;

    while (left <= right) {
        mid = (left + right) / 2;
        if (array[mid] == target) {
            pthread_mutex_lock(&lock);
            thread_result[thread_num] = mid;
            pthread_mutex_unlock(&lock);
            return NULL;
        } else if (array[mid] > target) {
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }

    return NULL;

}

在函数内部,首先从 input 中获取到左边界、右边界、查找目标和线程编号等信息,然后利用 while 循环进行二分查找。如果查找到目标元素,就使用锁将该线程的查找结果写入到 thread_result 数组中,并返回。否则,继续查找。如果没有查找到目标元素,函数返回 NULL。

  1. main 函数内部,首先从命令行参数中获取到要查找的目标数值,并初始化锁变量。
int target = atoi(argv[1]);

pthread_mutex_init(&lock, NULL);
  1. 接下来,将数组分为若干部分,每个线程负责一个子数组,并启动每个线程,进行查找。
int part_size = sizeof(array) / sizeof(int) / THREAD_NUM;
pthread_t threads[THREAD_NUM];
int inputs[THREAD_NUM][4];

for (int i = 0; i < THREAD_NUM; i++){
    int left = i * part_size;
    int right = (i == THREAD_NUM - 1) ? sizeof(array) / sizeof(int) - 1 : left + part_size - 1;
    inputs[i][0] = left;
    inputs[i][1] = right;
    inputs[i][2] = target;
    inputs[i][3] = i;
    pthread_create(&threads[i], NULL, binarySearch, inputs[i]);
}

在这里,首先计算出每个子数组的边界,然后将这些信息填充到一个 inputs 数组中。最后,启动 THREAD_NUM 个线程,并将 inputs 数组中的内容作为参数传递给 binarySearch 函数。

  1. 最后,在 main 函数中等待所有线程完成查找,并将结果合并。
for (int i = 0; i < THREAD_NUM; i++) {
    pthread_join(threads[i], NULL);
}

int result = -1;
for (int i = 0; i < THREAD_NUM; i++) {
    if (thread_result[i] != -1) {
        result = thread_result[i];
        break;
    }
}

if (result != -1) {
    printf("Target found at index %d\n", result);
} else {
    printf("Target not found\n");
}

pthread_mutex_destroy(&lock);

在这里,首先逐一等待所有线程结束,然后遍历 thread_result 数组,找到第一个不为 -1 的元素,如果找到了,则表示目标元素已经找到了,输出其下标,否则表示目标元素不存在于数组中,输出一条相关信息。最后,释放锁变量。

结论

本文介绍了如何使用 pthread 进行二分查找。在实际应用中,可以根据实际需要对代码进行修改和优化,以达到更好的性能和效果。