1. 程式人生 > >歸併排序--自上而下和自下而上兩種方法的實現

歸併排序--自上而下和自下而上兩種方法的實現

歸併排序思想

自上而下的遞迴

對一個數組(str)選中一箇中間位置(mid=(start+end)/2),分別進行左遞迴(mergeSort(str,start,mid,length)),右遞迴(mergeSort(str,mid+1,end,length)),在回朔的時候分別對以中間為分割的陣列進行排序(merge(str,start,end,mid)),此時是一個歸併的過程,這是自上而下的方法。

自下而上的遞迴

自下而上歸併其實就是自上而下的時候的回朔過程,先對每一個數字排序,在兩兩排序,在對結果兩兩排序,直到完成。

具體程式碼實現(自上而下)

int merge(long *str,int start,int end,int mid){
	long *tmp = (long *)malloc(sizeof(long)*(end-start+1));
	int i=start;
	int j=mid+1;	
	int k=0;
	while(i<=mid && j<=end){
		if(str[i]<str[j])
			tmp[k++]=str[i++];
		else
			tmp[k++]=str[j++];
	}
	while(i<=mid)
		tmp[k++] = str[i++];
	while(j<=end)
		tmp[k++] = str[j++];
	for(i=start;i<=end;i++)
		str[i]=tmp[i-start];
	free(tmp);
}
int mergeSort(long *str,int start ,int end,int length){
	if(str == NULL || start <0 || end >length || length <=0 || end <= start)
		return ;
	int mid = (start + end )/2;
	mergeSort(str,start,mid,length);
	mergeSort(str,mid+1,end,length);
	merge(str,start,end,mid);
}
void call(){
	long *array = (long *)malloc(sizeof(long)*10);
	genrand(10,array);
	mergeSort(array,0,9,10);
	int i=0;
	for(i;i<10;i++)
		printf("%ld\n",array[i]);
}

自下而上程式碼實現
void merge(long *str,int start ,int end,int mid){
	if(start>=end || mid >=end)
		return;
	int i =start;
	int j =mid+1;
	int k =0;
	long *tmp = (long *)malloc(sizeof(long)*(end-start+1));
	while(i<=mid && j<=end){
		if(str[i]<=str[j])
			tmp[k++]=str[i++];
		else
			tmp[k++]=str[j++];
		
	}
	while(i<=mid)
		tmp[k++]=str[i++];
	while(j<=end)
		tmp[k++]=str[j++];
	for(i=start;i<=end;i++)
		str[i]=tmp[i-start];

	free(tmp);
}
void mergeGroup(long *str,int len,int gap){
	int i=0;
	//需要歸併的總長度
	int twoLen = 2*gap;
	//因為陣列下標以0開始,所以要-1
	for(i=0;i+twoLen-1<len;i+=twoLen){
		//i是起點,起點+總長度-1 為終點,起點+每一個數組的長度-1為分割點
		merge(str,i,i+twoLen-1,i+gap-1);
	}
	//如果便利一遍後 分割點還是小於陣列最後一個下標,則表示還有最後一個歸併沒有完成,起點為i終點為len-1
	if(i+gap-1 < len-1)
		merge(str,i,len-1,i+gap-1);
}
void mergeSortDownUp(long * str,int length){
	int n;
	if(str == NULL || length<=0)
		return;
	//n 可以理解為每一次歸併的陣列長度
	for(n=1;n<length;n*=2)
		mergeGroup(str,length,n);
}
void call(){
	long *array = (long *)malloc(sizeof(long)*10);
	genrand(10,array);
	mergeSortDownUp(array,10);
	int i=0;
	for(i;i<10;i++)
		printf("%ld\n",array[i]);

}

genrand() 和swap()函式的實現如下。
int genrand(int num,long * array ){
	if (num>10000)
		return 0 ;
	srand((unsigned int)time(0));
	int i=0;
	for(i=0;i<num;i++)
		array[i] = rand();
	return 1;
	
}

void swap(long *A,long *B){
    long tmp;
    tmp = *A;
    *A = *B;
    *B = tmp;
}

執行環境:ubuntu14.04 、gcc

注:如有錯誤望批評指正。