標籤:style blog color 資料 for 演算法
一,歸併排序
歸併排序是建立在歸併操作上的一種排序演算法,它採用了分治法的思想,是一種穩定的排序演算法,而且歸併排序的速度僅次
於快速排序。時間複雜度:O(n*logn),最壞的情況:O(n*logn),空間複雜度:O(n)。從資料就可以看出:歸併排序比快速
排序快很多,同樣為穩定排序。
演算法的思想:將一個無序的數組不斷的分解成2個一組進行比較大小,並將比較後的部分數組按一定的順序排放好。然後再繼續將數組一部分進行比較,這樣就可以了直至成為一個完整的數組。
例子: 6 2 4 7 3 8
第一趟排序: 2 6 4 3 7 8
第二趟排序: 2 4 6 3 7 8
第三趟排序: 2 3 4 6 7 8
範例程式碼:
#include <stdio.h>void Merge(int arrayA[], int first, int mid, int last, int arrayB[]) //將分解的數組進行歸併{ int n = mid, m = last; int i = first, j = mid+1; int k = 0; while(i<=n && j<=m) //進行歸併操作 { if(arrayA[i] <= arrayA[j]) arrayB[k++] = arrayA[i++]; else arrayB[k++] = arrayA[j++]; } while(i<=n) { arrayB[k++] = arrayA[i++]; } while(j<=m) { arrayB[k++] = arrayA[j++]; } for(i = 0; i<k; i++) //將歸併好的數組按照一定的次序放回原來的數組 arrayA[first+i] = arrayB[i];}void MergeSort(int arrayA[], int first, int last, int arrayB[]) //將數組進行分解操作{ if(first < last) { int mid = (first+last)/2; MergeSort(arrayA, first, mid, arrayB); MergeSort(arrayA, mid+1, last, arrayB); Merge(arrayA, first, mid, last, arrayB); }}int main(){ int n; int arrayA[100], arrayB[100]; printf("請輸入要排序數組的大小:"); scanf("%d", &n); printf("請輸入數組中各個數:"); for(int i = 0; i<n; i++) scanf("%d", &arrayA[i]); MergeSort(arrayA, 0, n-1, arrayB); for(int i = 0; i<n; i++) printf("%d ",arrayB[i]); printf("\n"); for(int i = 0; i<n; i++) printf("%d ",arrayA[i]);}
二,用插入排序來最佳化歸併排序 歸併排序可以使得效率達到O(n*logn),但我們可以利用插入排序將歸併排序進一步最佳化,最佳化後的時間複雜度為:O(n*log(n/k)),k的取值範圍為:10到20左右,就是將數組切分成小於10個數來進行插入排序,這樣可以進一步減短歸併排序的開銷。因為在插入排序中,當n比較小時速度還是很快的。
最佳化後的代碼:
#include <stdio.h>void Merge(int arrayA[], int first, int mid, int last, int arrayB[]) //將排序好的部分數組進行歸併{ int n = mid, m = last; int i = first, j = mid+1; int k = 0; while(i<=n && j<=m) { if(arrayA[i] <= arrayA[j]) arrayB[k++] = arrayA[i++]; else arrayB[k++] = arrayA[j++]; } while(i<=n) { arrayB[k++] = arrayA[i++]; } while(j<=m) { arrayB[k++] = arrayA[j++]; } for(i = 0; i<k; i++) arrayA[first+i] = arrayB[i];}void InsertionSort(int arrayA[], int first, int last) //進行插入排序操作{ int mark; int i, j; for(i = first+1; i<=last; i++) { mark = arrayA[i]; j = i-1; while(j>=first && mark<arrayA[j]) { arrayA[j+1] = arrayA[j]; j--; } arrayA[j+1] = mark; }}void MergeSort(int arrayA[], int first, int last, int arrayB[]) //將數組進行分割,分割成每一塊小於10個數{ if((last-first)>10) //若大於10個數則進行分割 { int mid = (first+last)/2; MergeSort(arrayA, first, mid, arrayB); MergeSort(arrayA, mid+1, last, arrayB); Merge(arrayA, first, mid, last, arrayB); } else //若小於10個數則進行插入排序 { InsertionSort(arrayA, first, last); }}int main(){ int n; int arrayA[100], arrayB[100]; printf("請輸入要排序數組的大小:"); scanf("%d", &n); printf("請輸入數組中的各個數:"); for(int i = 0; i<n; i++) scanf("%d", &arrayA[i]); MergeSort(arrayA, 0, n-1, arrayB); for(int i = 0; i<n; i++) printf("%d ", arrayA[i]); return 0;}