1. 程式人生 > >C語言之合併排序

C語言之合併排序

一、基本運算:

兩路合併排序:將兩個有序序列合併成一個有序序列。

二、步驟:

①把待排序的序列分成長度為1的子序列(只包含一個記錄的序列被認為是有序的)→得到n個長度為1的有序子序列;

②實施兩兩合併,合併相鄰的兩個子序列→得到大約n/2個長度為2的有序子序列;

③重複步驟②,直到合併成一個長度為n的有序序列為止。

三、注意:

當待排序序列個數為奇數時,最後一個長度為1的子序列則在最後一趟進行排序。

四、舉例:

以對序列A[0], A[l]…, A[n-1]進行升序排列來進行講解,在此採用自頂向下的實現方法,操作步驟如下。

①將所要進行的排序序列分為左右兩個部分,如果要進行排序的序列的起始元素下標為first,最後一個元素的下標為last,那麼左右兩部分之間的臨界點下標mid=(first+last)/2,這兩部分分別是A[first … mid]和A[mid+1 … last]; 

②將上面所分得的兩部分序列繼續按照步驟(1)繼續進行劃分,直到劃分的區間長度為1;

③將劃分結束後的序列進行歸併排序,排序方法為對所分的n個子序列進行兩兩合併,得到n/2或n/2+l個含有兩個元素的子序列,再對得到的子序列進行合併,直至得到一個長度為n的有序序列為止。

五、函式:

Merge函式

①功能:將兩個有序序列合併成一個有序序列;

②C程式碼:

void Merge(int arr[],int low,int mid,int high)
{
	int left_low=low;					//左邊序列的左下標
	int left_high=mid;
	int right_low=mid+1;				//右邊序列的左下標
	int right_high=high;
	int tmp[N],k=0,i;					//陣列tmp用來存放序列元素
	while(left_low<=left_high&&right_low<=right_high)  //當左右序列都有元素時執行迴圈
	{
		if(arr[left_low]<arr[right_low])
			tmp[k++]=arr[left_low++];					//元素小的放進陣列tmp
		else
			tmp[k++]=arr[right_low++];
	}
	if(left_low<=left_high){							//左邊序列還有元素時
		for(i=left_low;i<=left_high;i++)
			tmp[k++]=arr[left_low++];
	}
	if(right_low<=right_high){							//右邊序列還有元素時
		for(i=right_low;i<=right_high;i++)
			tmp[k++]=arr[right_low++];
	}

	for(i=0;i<high-low+1;i++){							//將陣列tmp中的元素賦給陣列arr,從而陣列arr有序
		arr[low+i]=tmp[i];
	}
}

MergeSort函式

①功能:通過呼叫自身分裂子序列;通過呼叫Merge函式實現兩路合併排序。

②程式碼:

void MergeSort(int arr[],int first,int last)
{
    int mid = 0;
    if(first<last){
        mid = (first+last)/2;							/* 注意防止溢位 */
        MergeSort(arr, first, mid);
        MergeSort(arr, mid+1,last);
        Merge(arr,first,mid,last);
    }
}

六、程式碼
#include <stdio.h>
#include <stdlib.h>
#define N 7

void Merge(int arr[],int low,int mid,int high)
{
	int left_low=low;					//左邊序列的左下標
	int left_high=mid;
	int right_low=mid+1;				//右邊序列的左下標
	int right_high=high;
	int tmp[N],k=0,i;					//陣列tmp用來存放序列元素
	while(left_low<=left_high&&right_low<=right_high)  //當左右序列都有元素時執行迴圈
	{
		if(arr[left_low]<arr[right_low])
			tmp[k++]=arr[left_low++];					//元素小的放進陣列tmp
		else
			tmp[k++]=arr[right_low++];
	}
	if(left_low<=left_high){							//左邊序列還有元素時
		for(i=left_low;i<=left_high;i++)
			tmp[k++]=arr[left_low++];
	}
	if(right_low<=right_high){							//右邊序列還有元素時
		for(i=right_low;i<=right_high;i++)
			tmp[k++]=arr[right_low++];
	}

	for(i=0;i<high-low+1;i++){							//將陣列tmp中的元素賦給陣列arr,從而陣列arr有序
		arr[low+i]=tmp[i];
	}
}

void MergeSort(int arr[],int first,int last)
{
    int mid = 0;
    if(first<last){
        mid = (first+last)/2;							/* 注意防止溢位 */
        MergeSort(arr, first, mid);
        MergeSort(arr, mid+1,last);
        Merge(arr,first,mid,last);
    }
}

int main(){
    int i;
    int a[N]={32,12,56,78,76,45,36};
    printf ("排序前:");
    for(i=0;i<N;i++)
        printf("%d\t",a[i]);
    MergeSort(a,0,N-1);  // 排序
    printf ("\n排序後:");
    for(i=0;i<N;i++)
        printf("%d\t",a[i]); printf("\n");
    return 0;
}