歸併排序
基本思想:
歸併(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;
}
}
}