1. 程式人生 > >C++ 歸併排序,千萬級以上資料的排序

C++ 歸併排序,千萬級以上資料的排序

眾所周知,著名的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);
}