排序算法(二)

歸併排序

基本思想:

歸併(Merge)排序法是將兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序序列分爲若干個子序列,每個子序列是有序的。然後再把有序子序列合併爲整體有序序列。

歸併排序示例:



算法實現

void merge(int *arr,int *store,int start,int mid,int end)
{
	int i,j,k;
	for(i = start,k = start,j = mid +1; i <= mid && j <= end;k++)
		if(arr[i] < arr[j])
			store[k] = arr[i++];
		else
			store[k] = arr[j++];
	while(i <= mid)
		store[k++] = arr[i++];
	while(j <= end)
		store[k++] = arr[j++];
	
}

void merge_sort(int *arr, int *store, int size)
{
	
	int *temp,*src = arr;
	int i=0,len=1,mid,flag = 0;
	printf("merge sort before:\n");
	print(arr,size);
	printf("merge sort after:\n");
	
	while(len < size){
		mid = len;
		len = 2 * mid;
		i = 0;
		while(i + len < size){  //等長子表合併
			merge(src,store,i,i + mid - 1,i + len -1);
			i = i + len;
		}
		if(i + mid < size){  //不等長子表合併
			merge(src,store,i,i + mid - 1, size -1);
		}
		temp = src;// 將src指針指向store數組,
		src = store;//下次排序就將store數組作爲了要排序的數組,
		store = temp;//arr數組就作爲存儲結果的數組。
					 //這樣就可以避免不停地重複賦值數組,提高排序效率
		flag++;//記錄歸併的次數,若是爲偶數次,則說明結果
				//存儲在arr數組裏面,這時應該將結果賦值到store數組裏。
	}
	printf("flag = %d\n",flag);
	if(flag % 2 == 0){
		for( i = 0; i < size; i++)
			store[i] = arr[i];
		print(store,size);
	}
		
}




快速排序

基本思想:

1)選擇一個基準元素,通常選擇第一個元素或者最後一個元素,

2)通過一趟排序講待排序的記錄分割成獨立的兩部分,其中一部分記錄的元素值均比基準元素值小。另一部分記錄的 元素值比基準值大。

3)此時基準元素在其排好序後的正確位置

4)然後分別對這兩部分記錄用同樣的方法繼續進行排序,直到整個序列有序。

快速排序的示例:




算法實現

int partition(int *arr, int start, int end)
{
	int value = arr[start];
	while(start < end){
		while(start < end && arr[end] >= value)
			end--;
		arr[start] = arr[end];
		while(start < end && arr[start] <= value)
			start++;
		arr[end] = arr[start];
	}
	arr[start] = value;
	return start;
}



遞歸實現

void quick_sort(int *arr, int start, int end)
{
	
	int pos;
	if(start < end){
		pos = partition(arr,start,end);
		quick_sort(arr,start,pos - 1);
		quick_sort(arr,pos + 1,end);
	}

}



非遞歸實現

void quick_sort(int *arr, int start, int end)
{
	int mystack[32];//自定義一個棧
	int top = -1;
	mystack[++top] = start;//起始點入棧
	mystack[++top] = end;//終止點入棧
	int  i,j,value;
	
	while(top > 0){
		j = end = mystack[top--];
		i = start = mystack[top--];
		value = arr[start];//選取第一個元素爲哨兵
		while( i < j){
			while(i<j && arr[j] >= value)
				j--;
			arr[i] = arr[j];
			while(i<j && arr[i] <= value)
				i++;
			arr[j] = arr[i];
		}
		arr[i] = value;//得到哨兵的位置
		
		if(end - i > 1){//哨兵位置右側多於一個元素,則說明還需要排序
			mystack[++top] = i + 1;//起始點、終止點入棧
			mystack[++top] = end;
		}
		
		if(i - start > 1){//同理
			mystack[++top] = start;
			mystack[++top] = i - 1;
		}
	}
	
	
}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章