C++ 歸併排序,千萬級以上資料的排序
阿新 • • 發佈:2018-12-23
眾所周知,著名的8大排序演算法相信大家都看過,但我唯獨對歸併排序是情有獨鍾。因為這個演算法,是一個可以輕鬆而愉快的進行並行排序的東西,而且歸併排序是穩定的。當數量達到一定級別的時候,無論再優秀的演算法,都會消耗一定的時間。所以,這個時候,就必須利用多執行緒去加速計算,但多執行緒又是一個極其難以控制的東西,因為必須將主體分為絕對互不影響的N部分就分別計算後統一,恰恰歸併排序就有這個性質,並且還是均分的。歸併的思想是什麼呢?是分治。就是說把一個大的個體分成N部分,劃分後去解決一個問題可以使得問題變得簡單或得到更快的速度。
廢話不多說,先看看測試,我的測試是對2600W左右的資料進行排序(跑億級的資料2個執行緒估計還是得費點時間),因為我為了簡單僅僅做了個例程,設計上就只開2個執行緒和單執行緒對比下而已,看看有莫得問題,實際應用這種設計肯定不行的哈。這個還是算上建立執行緒等額外耗時,基本上都有2倍左右的差距
#include<Windows.h> #include <cstdlib> #include <ctime> #include <iostream> #include <process.h> #include <csignal> #include <map> using namespace std; int threadIdentity[2]; map<string, void*> _map; void Merge(int* src,int start,int mid,int end,int* tmp) { int i, j, k; for(i=start,j=mid+1,k=start;i<=mid&&j<=end;) { if(src[i]<src[j]) { tmp[k++] = src[i++]; } else { tmp[k++] = src[j++]; } } for(;i<=mid;++i) { tmp[k++] = src[i]; } for(;j<=end;++j) { tmp[k++] = src[j]; } for(i=start;i<=end;++i) { src[i] = tmp[i]; } } void MergeSort(int* src,int start,int end,int* tmp) { if(start<end) { int mid = (start + end) / 2 ; MergeSort(src, start, mid,tmp); MergeSort(src, mid + 1, end,tmp); Merge(src, start, mid, end, tmp); } } void print(int* src,int start,int end) { for (int i = start; i<=end; ++i) { cout << src[i] << ' '; } cout << endl<<endl; } struct MultiArith_ { int identity; int* src; int* tmp; int start; int end; }; unsigned _stdcall multiArith(void* arg) { MultiArith_* pma = (MultiArith_*)arg; MergeSort(pma->src, pma->start, pma->end, pma->tmp); threadIdentity[pma->identity] = 1; raise(SIGINT); return 0; } void handler(int sig) { if(threadIdentity[0]==1&&threadIdentity[1]==1) { int* src = (int*)_map["a"]; int* tmp = (int*)_map["tmp"]; int size = *(int*)_map["size"]; // print(src, 0, (size - 1) / 2); // print(src, (size - 1) / 2 + 1, size - 1); Merge(src, 0, (size - 1) / 2, size - 1, tmp); // print(src, 0,size-1); cout << "Finished!2 Thread Use Time(ms):" << clock() - *(clock_t*)_map["t1"] << endl; for (int i = 0; i<size; ++i) { src[i] = rand(); } clock_t t1 = clock(); MergeSort(src, 0, size - 1, tmp); cout << "Finished!Use Time(ms):" << clock() - t1 << endl; } signal(SIGINT, handler); } int main() { signal(SIGINT, handler); srand(time(0)); int size = 1024/4*1024*1024/10; int* a = (int*)malloc(sizeof(int)*size); int* tmp = (int*)malloc(sizeof(int)*size); int mid = (size - 1) / 2; for (int i = 0; i<size; ++i) { a[i] = rand(); } //print(a, 0, size - 1); _map["a"] = a; _map["tmp"] = tmp; _map["size"] = &size; MultiArith_ ma[2]; ma[0].src = a; ma[0].tmp = tmp; ma[0].start = 0; ma[0].end = mid; ma[0].identity = 0; ma[1].src = a; ma[1].tmp = tmp; ma[1].start = mid+1; ma[1].end = size-1; ma[1].identity = 1; threadIdentity[0] = 0; threadIdentity[1] = 0; clock_t t1 = clock(); _map["t1"] = &t1; _beginthreadex(0, 0, multiArith, &ma[0], 0, 0); _beginthreadex(0, 0, multiArith, &ma[1], 0, 0); Sleep(INFINITE); }