1. 程式人生 > >資料結構排序之合併排序

資料結構排序之合併排序

合併排序是用分治策略的一個排序演算法。

其基本思想是將待排序元素分成大小大致相同的兩個子序列,對兩個子序列進行排序後,再進行合併。

通俗來講,待排序元素不停的分解與合併,這是一個重複且相似的過程。

假設有n個元素,我們將其劃分兩半,再對其中的一部分再劃分兩半,重複此操作,直至最小序列長度為2或3的時候,我們對最小序列進行分解按大小合併,我們就得到一個排序成功的最小子序列,再將其與同級的最小子序列(已經做了同樣操作排過序)進行按大小合併。重複此操作,直到 n/2長度的序列與n/2長度的序列合併,合併排序算完成。

merge函式   用來合併p-q 與 q-r 兩個長度序列(按照遞增序列)

void merge(int num[],int p,int q,int r)
{
	int n1 = q - p + 1;          //前半段的長度 
	int n2 = r - q + 1;			 //後半段的長度 
	int left[n1+1], right[n2];
	
	for(int i = 0; i < n1;++i) 
		left[i] = num[p + i];	//將前半段複製到左邊 
	left[n1] = 65536;			//最後一位設定為大值防止排序時出錯 
	for(int j = 0; j < n2; ++j)
		right[j] = num[q + j + 1];	//將後半段複製到右邊 
	right[n2-1] = 65536;	
	
	int i = 0,j = 0;
	for(int x = p ; x <= r; x++ )   //將左右合併 
	{
		if (left[i] < right[j])		
		{
			num[x] = left[i++];
		}
		else
		{
			num[x] = right[j++];
		}
	}
}

mergeSort函式  劃分區域

void mergeSort(int num[],int p,int r)
{
	if(p < r)		//當p=r的時候說明只有1個元素,最低也要有2個元素 
	{
		int q = (p + r) / 2;       //劃分位置 
		mergeSort(num, p, q);		//將左邊進行歸併排序 
		mergeSort(num, q+1, r);		//將右邊進行歸併排序 
		merge(num, p, q, r);		//將左右合併 
	}
}

時間複雜度:

       因為每次會分成大致均等的兩部分,所以對於n個元素,它大概會合並O(log₂n)次,而每個量級區域的合併總時間是O(n) (不管劃分多少區域,總數量還是n),所以合併排序的時間複雜度是O(n*log₂n)

#include <iostream>
#include <stdlib.h>
using namespace std;

void merge(int num[],int p,int q,int r)
{
	int n1 = q - p + 1;
	int n2 = r - q + 1;
	int left[n1+1], right[n2];
	
	for(int i = 0; i < n1;++i) 
		left[i] = num[p + i];
	left[n1] = 65536;
	for(int j = 0; j < n2; ++j)
		right[j] = num[q + j + 1];
	right[n2-1] = 65536;	
	
	int i = 0,j = 0;
	for(int x = p ; x <= r; x++ )
	{
		if (left[i] < right[j])
		{
			num[x] = left[i++];
		}
		else
		{
			num[x] = right[j++];
		}
	}
}

void mergeSort(int num[],int p,int r)
{
	if(p < r)
	{
		int q = (p + r) / 2;
		mergeSort(num, p, q);
		mergeSort(num, q+1, r);
		merge(num, p, q, r);
	}
}

int main()
{
	int max;
	cin >> max;
	int num[max];
	for(int i = 0; i < max; i++)
	{
		num[i] = rand() % 100;
	}
	mergeSort(num,0,max-1);
	for(int i = 0;i < max; i++)
	{
		printf("%d ",num[i]);
	}
	
	return 0;
}