📜  使用多线程程序的给定数组的非重复元素

📅  最后修改于: 2021-05-17 18:20:07             🧑  作者: Mango

给定大小为N的数组arr []和代表线程数的整数T ,任务是使用多线程查找所有非重复的数组元素。

例子:

方法:想法是使用C++中可用的pthread库为并发进程流创建多个线程,并在多线程程序中执行多个操作(pthread create,pthread join,lock等)。请按照以下步骤解决问题:

  • 将数组划分为T个子数组,以便每个大小为N / T的子数组将在单个线程中执行。
  • 初始化一个映射,例如mp ,以存储每个数组元素的频率。
  • 创建一个pthread_mutex_lock,例如lock1 ,以确保所有线程都不会彼此跳闸并破坏Map容器。
  • 定义一个函数func()来执行线程的主体。此函数通常称为线程内核,是在线程创建过程中提供的。
    • 使用pthread_mutex_lock()锁定当前线程,使其不与其他线程重叠
    • 遍历给定范围作为数组arr []中函数func()的参数,并增加遇到的数组元素的频率。
    • 使用函数pthread_mutex_unlock()释放当前线程。
  • 初始化一个类型为pthread_t的数组,例如thread [] ,用于存储线程。
  • 遍历范围[0,T]并通过调用pthread_create()函数创建线程并将其存储在线程中[i]
  • 当每个线程执行其各自的任务时, main()函数将需要等待,直到每个线程完成其工作。
    • 使用pthread_join()函数等待,直到每个线程完成执行函数func()为止
    • 遍历范围[0,T]并为每个线程[i]调用pthread_create()函数
  • 最后,遍历map mp并打印仅出现一次的元素。

下面是上述方法的实现:

C++
// C++ program to implement
// the above approach
  
#include 
#include 
using namespace std;
  
// Structure of subarray 
// of the array
struct range_info {
  
    // Stores start index
    // of the subarray
    int start;
  
    // Stores end index
    // of the subarray
    int end;
  
    // Stores pointer to the
    // first array element
    int* a;
};
  
  
// Declaring map, and mutex for
// thread exclusion(lock)
map mp;
pthread_mutex_t lock1;
  
  
// Function performed by every thread to
// count the frequency of array elements
// in current subarray
void* func(void* arg)
{
    // Taking a lock so that threads
    // do not overlap each other
    pthread_mutex_lock(&lock1);
      
      
    // Initalize range_info 
    // for each thread
    struct range_info* rptr 
    = (struct range_info*)arg;
  
  
    // Thread is going through the array
    // to check and update the map
    for (int i = rptr->start; 
            i <= rptr->end; i++) {
                      
          
        // Stores iterator to the map         
        map::iterator it;
          
          
        // Update it
        it = mp.find(rptr->a[i]);
          
          
        // If rptr->a[i] not found
        // in map mp
        if (it == mp.end()) {
              
              
            // Insert rptr->a[i] with 
            // frequency 1
            mp.insert({ rptr->a[i], 1 });
        }
        else {
              
              
            // Update frequency of
            // current element
            it->second++;
        }
    }
      
  
    // Thread releases the lock
    pthread_mutex_unlock(&lock1);
    return NULL;
}
  
  
// Function to find the unique
// numbers in the array
void numbers_occuring_once(int arr[],
                        int N, int T)
{
    // Stores all threads
    pthread_t threads[T];
  
    // Stores start index of
    // first thread
    int spos = 0;
  
    // Stores last index 
    // of the first thread
    int epos = spos + (N / T) - 1;
  
    // Traverse each thread
    for (int i = 0; i < T; i++) {
  
        // Initalize range_info for
        // current thread
        struct range_info* rptr
            = (struct range_info*)malloc(
                sizeof(struct range_info));
  
        // Update start index of
        // current subarray     
        rptr->start = spos;
  
        // Stores end index of
        // current subarray
        rptr->end = epos;
  
        // Update pointer to the first
        // element of the array
        rptr->a = arr;
          
          
        // creating each thread with 
        // appropriate parameters
        int a
        = pthread_create(&threads[i], NULL,
                        func, (void*)(rptr));
                          
                          
        // updating the parameters 
        // for the next thread
        spos = epos + 1;
        epos = spos + (N / T) - 1;
        if (i == T - 2) {
            epos = N - 1;
        }
    }
  
    // Waiting for threads to finish
    for (int i = 0; i < T; i++) {
        int rc 
        = pthread_join(threads[i], NULL);
    }
  
    // Traverse the map
    for (auto it: mp) {
                  
                  
                                      
    // If frequency of current 
    // element is 1                             
        if (it.second == 1) {
  
            // Print the element
            cout << it.first << " ";
        }
    }
}
  
  
// Drivers Code
int main()
{
    // initializing the mutex lock 
    pthread_mutex_init(&lock1, NULL);
    int T = 3;
    int arr[] = { 1, 0, 5, 5, 2, 6 };
    int N = sizeof(arr) / sizeof(arr[0]);
    numbers_occuring_once(arr, N, T);
}


输出:

时间复杂度: O(N * log(N))
辅助空间: O(N)

注意:建议使用以下命令在基于Linux的系统中执行程序: