歸併排序:歸併排序(英語:Merge sort,或mergesort),是建立在歸併操做上的一種有效的排序算法,效率爲O(n log n)。1945年由約翰·馮·諾伊曼首次提出。該算法是採用分治法(Divide and Conquer)的一個很是典型的應用,且各層分治遞歸能夠同時進行。ios
歸併排序的核心思想是將兩個有序的數列合併成一個大的有序的序列。經過遞歸,層層合併,即爲歸併。算法
如圖,從下到上,每一步都須要將兩個已經有序的子數組合併成一個大的有序數組,以下是實現合併的具體代碼,請讀者細細體會數組
1 void merge(int arr[],int l,int mid,int r) 2 { 3 int aux[r-l+1];//開闢一個新的數組,將原數組映射進去 4 for(int m=l;m<=r;m++) 5 { 6 aux[m-l]=arr[m]; 7 } 8 9 int i=l,j=mid+1;//i和j分別指向兩個子數組開頭部分 10 11 for(int k=l;k<=r;k++) 12 { 13 if(i>mid) 14 { 15 arr[k]=aux[j-l]; 16 j++; 17 } 18 else if(j>r) 19 { 20 arr[k]=aux[i-l]; 21 i++; 22 } 23 else if(aux[i-l]<aux[j-l]) 24 { 25 arr[k]=aux[i-l]; 26 i++; 27 } 28 else 29 { 30 arr[k]=aux[j-l]; 31 j++; 32 } 33 } 34 }
上圖代碼已經完成了歸併中的「並」這一部分,歸併歸併,有並必有歸,以下實現「歸」的部分ide
1 void merge_sort(int arr[],int l,int r) 2 { 3 if(l >=r) 4 return ; 5 int mid=(l+r)/2; 6 merge_sort(arr,l,mid); 7 merge_sort(arr,mid+1,r); 8 merge(arr,l,mid,r); 9 }
因爲上圖中的l,r不方便使用者調用,因而咱們建立一個方便本身調用的my_merge_sort函數函數
1 void my_merge_sort(int arr[],int n) 2 { 3 merge_sort(arr,0,n-1); 4 }
以上咱們便實現了歸併排序中的歸和並,歸併排序是利用二分法實現的排序算法,時間複雜度爲nlogn,是一種比較快速的排序算法。以下是筆者本身寫的歸併排序的所有代碼,spa
1 #include <iostream> 2 using namespace std; 3 4 5 void merge(int arr[],int l,int mid,int r) 6 { 7 int aux[r-l+1];//開闢一個新的數組,將原數組映射進去 8 for(int m=l;m<=r;m++) 9 { 10 aux[m-l]=arr[m]; 11 } 12 13 int i=l,j=mid+1;//i和j分別指向兩個子數組開頭部分 14 15 for(int k=l;k<=r;k++) 16 { 17 if(i>mid) 18 { 19 arr[k]=aux[j-l]; 20 j++; 21 } 22 else if(j>r) 23 { 24 arr[k]=aux[i-l]; 25 i++; 26 } 27 else if(aux[i-l]<aux[j-l]) 28 { 29 arr[k]=aux[i-l]; 30 i++; 31 } 32 else 33 { 34 arr[k]=aux[j-l]; 35 j++; 36 } 37 } 38 } 39 //遞歸的使用歸併排序,對arr[l....r]排序 40 void merge_sort(int arr[],int l,int r) 41 { 42 if(l >=r) 43 return ; 44 int mid=(l+r)/2; 45 merge_sort(arr,l,mid); 46 merge_sort(arr,mid+1,r); 47 merge(arr,l,mid,r); 48 } 49 50 void my_merge_sort(int arr[],int n) 51 { 52 merge_sort(arr,0,n-1); 53 } 54 55 int main() 56 { 57 int a[6]; 58 for(int i=0;i<6;i++) 59 { 60 cin>>a[i]; 61 } 62 my_merge_sort(a,6); 63 for(int i=0;i<6;i++) 64 { 65 cout<<a[i]<<" "; 66 } 67 return 0; 68 }
上面實現的歸併排序是自頂向下的,咱們能夠以另一種方向來實現歸併,改遞歸爲迭代。以下實現3d
1 #include <iostream> 2 #include <math.h> 3 using namespace std; 4 5 void merge(int arr[],int l,int mid,int r) 6 { 7 int aux[r-l+1];//開闢一個新的數組,將原數組映射進去 8 for(int m=l;m<=r;m++) 9 { 10 aux[m-l]=arr[m]; 11 } 12 13 int i=l,j=mid+1;//i和j分別指向兩個子數組開頭部分 14 15 for(int k=l;k<=r;k++) 16 { 17 if(i>mid) 18 { 19 arr[k]=aux[j-l]; 20 j++; 21 } 22 else if(j>r) 23 { 24 arr[k]=aux[i-l]; 25 i++; 26 } 27 else if(aux[i-l]<aux[j-l]) 28 { 29 arr[k]=aux[i-l]; 30 i++; 31 } 32 else 33 { 34 arr[k]=aux[j-l]; 35 j++; 36 } 37 } 38 } 39 40 void mergesort(int arr[],int n) 41 { 42 for(int sz=1;sz<=n;sz+=sz) 43 { 44 for(int i=0;i+sz<n;i+=sz+sz)//i+sz防止越界 45 {//對arr[i...sz-1]和arr[i+sz.....i+2*sz-1]進行排序 46 merge(arr,i,i+sz-1,min(i+sz+sz-1,n-1)); //min函數防止越界 47 } 48 } 49 50 } 51 52 int main() 53 { 54 int a[5]; 55 for(int i=0;i<5;i++) 56 { 57 cin>>a[i]; 58 } 59 mergesort(a,5); 60 for(int i=0;i<5;i++) 61 { 62 cout<<a[i]<<" "; 63 } 64 return 0; 65 }