เราได้รับอาร์เรย์จำนวนเต็มที่ไม่ได้จัดเรียง งานคือการจัดเรียงอาร์เรย์โดยใช้เทคนิค Merge Sort ที่นำไปใช้ผ่าน Multi-threading
Merge Sort
Merge Sort เป็นเทคนิคการจัดเรียงที่อิงตามเทคนิค Divide and Conquer (แบ่งและเอาชนะ) โดยเราแบ่งอาร์เรย์ออกเป็นครึ่งๆ เท่าๆ กัน แล้วนำมารวมกันในลำดับที่จัดเรียงแล้ว
อัลกอริทึมการนำ Merge Sort ไปใช้
ตรวจสอบว่ามีสมาชิกหนึ่งตัวในรายการหรือไม่ หากมี ให้คืนค่าสมาชิกนั้น
ถ้าไม่ใช่ ให้แบ่งข้อมูลแบบ Recursive (เรียกซ้ำ) ออกเป็นสองครึ่ง จนกว่าจะไม่สามารถแบ่งได้อีก
สุดท้าย ให้รวมรายการย่อยๆ เข้าด้วยกันเป็นรายการใหม่ในลำดับที่จัดเรียงแล้ว
Multi-Threading (หลายเธรด)
ในระบบปฏิบัติการ Threads (เธรด) เป็นกระบวนการที่มีน้ำหนักเบา (Lightweight Process) ซึ่งรับผิดชอบในการดำเนินการส่วนหนึ่งของงาน เธรดต่างๆ แบ่งปันทรัพยากรร่วมกันเพื่อดำเนินการงานพร้อมกัน (Concurrently)
Multi-threading เป็นการนำ Multitasking ไปใช้จริง โดยที่เราสามารถรันเธรดหลายตัวบนโปรเซสเซอร์เดียว เพื่อดำเนินการงานพร้อมกัน มันแบ่งย่อยการดำเนินการเฉพาะภายในแอปพลิเคชันเดียวออกเป็นเธรดแต่ละตัว แต่ละเธรดสามารถรันแบบขนาน (Parallel) ได้
ตัวอย่าง
Input - int arr[] = {3, 2, 1, 10, 8, 5, 7, 9, 4}
Output - Sorted array is: 1, 2, 3, 4, 5, 7, 8, 9, 10
คำอธิบาย - เราได้รับอาร์เรย์ที่ไม่ได้จัดเรียงพร้อมค่าจำนวนเต็ม ตอนนี้เราจะจัดเรียงอาร์เรย์โดยใช้ Merge Sort กับ Multithreading
Input - int arr[] = {5, 3, 1, 45, 32, 21, 50}
Output - Sorted array is: 1, 3, 5, 21, 32, 45, 50
คำอธิบาย - เราได้รับอาร์เรย์ที่ไม่ได้จัดเรียงพร้อมค่าจำนวนเต็ม ตอนนี้เราจะจัดเรียงอาร์เรย์โดยใช้ Merge Sort กับ Multithreading
วิธีการที่ใช้ในโปรแกรมด้านล่าง
เราจะเริ่มต้นด้วยการสร้างตัวเลขสุ่มโดยใช้เมธอด rand() ใน C++ STL
สร้างอาร์เรย์ของ pthread_t คือ P_TH[thread_size]
เริ่มลูป FOR จาก i=0 ถึง i น้อยกว่าขนาดเธรด ภายในลูป เรียก pthread_create(&P_TH[i], NULL, Sorting_Threading, (void*)NULL) เพื่อสร้างเธรดพร้อมค่าอาร์เรย์ที่กำหนด
เรียกฟังก์ชัน combine_array(0, (size/2-1)/2, size/2-1), combine_array(size/2, size/2+(size-1-size/2)/2, size-1) และ combine_array(0, (size-1)/2, size-1)
พิมพ์อาร์เรย์ที่จัดเรียงแล้วเก็บใน arr[] แบบจำนวนเต็ม
ภายในฟังก์ชัน void* Sorting_Threading(void* arg)
ประกาศตัวแปร set_val เป็น temp_val++, first เป็น set_val*(size/4), end เป็น (set_val+1)*(size/4)-1 และ mid_val เป็น first+(end-first)/2
ตรวจสอบ IF first น้อยกว่า end แล้วเรียก Sorting_Threading(first, mid_val), Sorting_Threading(mid_val+1, end) และ combine_array(first, mid_val, end)
ภายในฟังก์ชัน void Sorting_Threading(int first, int end)
ประกาศตัวแปร mid_val เป็น first+(end-first)/2
ตรวจสอบ IF first น้อยกว่า end แล้วเรียก Sorting_Threading(first, mid_val), Sorting_Threading(mid_val+1, end) และ combine_array(first, mid_val, end)
ภายในฟังก์ชัน void combine_array(int first, int mid_val, int end)
ประกาศตัวแปร int* start = new int[mid_val-first+1], int* last = new int[end-mid_val], temp_1 = mid_val-first+1, temp_2 = end-mid_val, i, j, k = first
เริ่มลูป FOR จาก i=0 ถึง i น้อยกว่า temp_1 ภายในลูป ตั้งค่า start[i] = arr[i+first]
เริ่มลูป FOR จาก i=0 ถึง i น้อยกว่า temp_2 ภายในลูป ตั้งค่า last[i] = arr[i+mid_val+1]
ตั้งค่า i=j=0 เริ่มลูป While i น้อยกว่า temp_1 AND j น้อยกว่า temp_2 ภายใน while ตรวจสอบ IF start[i] น้อยกว่าหรือเท่ากับ last[j] แล้วตั้งค่า arr[k++] = start[i++] มิฉะนั้น ตั้งค่า arr[k++] = last[j++]
เริ่ม WHILE i น้อยกว่า temp_1 แล้วตั้งค่า arr[k++] = start[i++] เริ่ม WHILE j น้อยกว่า temp_2 แล้วตั้งค่า arr[k++] = last[j++]
ตัวอย่างโค้ด
#include <iostream>
#include <pthread.h>
#include <time.h>
#define size 20
#define thread_size 4
using namespace std;
int arr[size];
int temp_val = 0;
void combine_array(int first, int mid_val, int end) {
int* start = new int[mid_val - first + 1];
int* last = new int[end - mid_val];
int temp_1 = mid_val - first + 1;
int temp_2 = end - mid_val;
int i, j;
int k = first;
for(i = 0; i < temp_1; i++) {
start[i] = arr[i + first];
}
for (i = 0; i < temp_2; i++) {
last[i] = arr[i + mid_val + 1];
}
i = j = 0;
while(i < temp_1 && j < temp_2) {
if(start[i] <= last[j]) {
arr[k++] = start[i++];
} else {
arr[k++] = last[j++];
}
}
while (i < temp_1) {
arr[k++] = start[i++];
}
while (j < temp_2) {
arr[k++] = last[j++];
}
}
void Sorting_Threading(int first, int end) {
int mid_val = first + (end - first) / 2;
if(first < end) {
Sorting_Threading(first, mid_val);
Sorting_Threading(mid_val + 1, end);
combine_array(first, mid_val, end);
}
}
void* Sorting_Threading(void* arg) {
int set_val = temp_val++;
int first = set_val * (size / 4);
int end = (set_val + 1) * (size / 4) - 1;
int mid_val = first + (end - first) / 2;
if (first < end) {
Sorting_Threading(first, mid_val);
Sorting_Threading(mid_val + 1, end);
combine_array(first, mid_val, end);
}
}
int main() {
for(int i = 0; i < size; i++) {
arr[i] = rand() % 100;
}
pthread_t P_TH[thread_size];
for(int i = 0; i < thread_size; i++) {
pthread_create(&P_TH[i], NULL, Sorting_Threading, (void*)NULL);
}
for(int i = 0; i < 4; i++) {
pthread_join(P_TH[i], NULL);
}
combine_array(0, (size / 2 - 1) / 2, size / 2 - 1);
combine_array(size / 2, size/2 + (size-1-size/2)/2, size - 1);
combine_array(0, (size - 1)/2, size - 1);
cout<<"Merge Sort using Multi-threading: ";
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
return 0;
}
ผลลัพธ์
หากเรารันโค้ดข้างต้น จะได้ผลลัพธ์ดังนี้:
Merge Sort using Multi-threading: 15 21 26 26 27 35 36 40 49 59 62 63 72 77 83 86 86 90 92 93