複習資料結構:排序演算法(四)——歸併排序

bigface1234fdfg發表於2015-02-23

    

    基本思想:基於分治法,即把待排序的陣列序列,分為若干個子序列,對每個子序列排序,然後再把所有有序的子序列合併為一個整體有序的序列。分析可知,如果拿任何一個元素作為子序列,那麼所有子序列就已經是有序的,而歸併排序的關鍵就在於如何合併,也就是“歸併”。


    歸併排序是外排序,穩定排序,時間複雜度是O(nlogn).




    詳細說歸併排序的過程:1個元素的表總是有序的。所以對n個元素的待排序列,每個元素可看成1個有序子表。對子表兩兩合併生成n/2個子表,所得子表除最後一個子表長度可能為1 外,其餘子表長度均為2。再進行兩兩合併,直到生成n 個元素按關鍵碼有序的表。

 

    程式碼如下:


非遞迴實現:(經過除錯,該程式有bug,後續修正!)

#include<iostream>
using namespace std; 

void Merge(int* r, int* rf, int i, int m, int n)
{
	int j, k; 
	for(j = m+1, k = i; i <= m && j <= n; k++)  // i記錄第一個子序列標記,j記錄第二個子序列標記,k記錄合併後序列標記
	{
		if(r[j] < r[i])  //  存入較小者
			rf[k] = r[j++]; 
		else
			rf[k] = r[i++]; 
	}
	while(i <= m)  // 如果不等長,就會出現這種情況
		rf[k++] = r[i++]; 
	while(j <= n)
		rf[k++] = r[j++]; 

	for(int ii = 0; ii < n+1; ii++)
		cout<<rf[ii]<<' '; 
	cout<<endl; 
}

void MergeSort(int* r, int* rf, int length)
{
	int len = 1; 
	int* q = r; 
	//int* tmp; 
	while(len < length)
	{
		int s = len; 
		len = 2*s; // 等長的兩個子序列,長度相同
		int i = 0; 
		bool flag = true; 
		while(i + len <= length)  // 等長的兩個子序列合併
		{
			cout<<"等長"<<i<<'-'<<i+s-1<<'-'<<i+len-1<<endl; 
			Merge(q, rf, i, i+s-1, i+len-1);  // 注意起始位置的標記
			i += len;  // 下一次合併的起始
			flag = false; 
		}
		if(i + s <= length)  // 不等長兩個子序列合併
		{
			cout<<"不等長"<<i<<'-'<<i+s-1<<'-'<< length-1<<endl; 
			Merge(q, rf, i, i+s-1, length-1);  // 注意最後的結束標記位置
		}
		
		cout<<"flag="<<flag<<endl; 
		if(!flag)
			swap(q, rf);  // 交換指標,該次合併的結果作為下次合併的起始
	}
}

int main()
{
	int a[10] = {11,1,5,7,2,4,9,6,10};  // ,9,6,10,8
	int b[10]; 
	MergeSort(a, b, 9); 

	for(int i = 0; i< 9; i++)
		cout<<b[i]<<' '; 
	cout<<endl; 

	return 0; 

}


遞迴實現:

void MSort(ElemType *r, ElemType *rf,int s, int t)  
{   
    ElemType *rf2;  
    if(s==t) r[s] = rf[s];  
    else  
    {   
        int m=(s+t)/2;          /*平分*p 表*/  
        MSort(r, rf2, s, m);        /*遞迴地將p[s…m]歸併為有序的p2[s…m]*/  
        MSort(r, rf2, m+1, t);      /*遞迴地將p[m+1…t]歸併為有序的p2[m+1…t]*/  
        Merge(rf2, rf, s, m,t);   /*將p2[s…m]和p2[m+1…t]歸併到p1[s…t]*/  
    }  
}  
void MergeSort_recursive(ElemType *r, ElemType *rf, int n)  
{   /*對順序表*p 作歸併排序*/  
    MSort(r, rf,0, n-1);  
}  


參考:

http://blog.csdn.net/xiazdong/article/details/8462393

http://blog.csdn.net/hguisu/article/details/7776068

http://blog.csdn.net/jetjetlinuxsystem/article/details/6589093


相關文章