歸併排序時間複雜度----主定理
阿新 • • 發佈:2018-12-31
http://blog.csdn.net/touch_2011/article/details/6785881
1、序言
2、歸併排序
2.1 引出
歸併排序又是另一類排序演算法,它是一種基於“分治”策略的一種演算法。歸併排序演算法是典型的分治演算法,對於規模較大的問題,可以分解成若干容易求解的簡單的問題,最後把解合併構成初始問題的解。詳細的排序過程可以參考《資料結構》或者《演算法導論》。
2.2 程式碼
- #include<stdio.h>
- #include<stdlib.h>
- #define INFINITE 1000
- //對兩個序列進行合併,陣列從mid分開
- //對a[start...mid]和a[start+1...end]進行合併
- void merge(int *a,int start,int mid,int end)
- {
- int i,j,k;
- //申請輔助陣列
- int *array1=(int *)malloc(sizeof(int)*(mid-start+2));
- int *array2=(int *)malloc(sizeof(int)*(end-mid+1));
- //把a從mid分開分別賦值給陣列
- for(i=0;i<mid-start+1;i++)
- *(array1+i)=a[start+i];
- *(array1+i)=INFINITE;//作為哨兵
- for(i=0;i<end-mid;i++)
- *(array2+i)=a[i+mid+1];
- *(array2+i)=INFINITE;
- //有序的歸併到陣列a中
- i=j=0;
- for(k=start;k<=end;k++){
- if(*(array1+i) > *(array2+j)){
- a[k]=*(array2+j);
- j++;
- }
- else{
- a[k]=*(array1+i);
- i++;
- }
- }
- free(array1);
- free(array2);
- }
- //歸併排序
- void mergeSort(int *a,int start,int end)
- {
- int mid=(start+end)/2;
- if(start<end){
- //分解
- mergeSort(a,start,mid);
- mergeSort(a,mid+1,end);
- //合併
- merge(a,start,mid,end);
- }
- }
- void main()
- {
- int i;
- int a[7]={0,3,5,8,9,1,2};//不考慮a[0]
- mergeSort(a,1,6);
- for(i=1;i<=6;i++)
- printf("%-4d",a[i]);
- printf("\n");
- }
2.3 效率分析
可以說合並排序是比較複雜的排序,特別是對於不瞭解分治法基本思想的同學來說可能難以理解。總時間=分解時間+解決問題時間+合併時間。分解時間就是把一個待排序序列分解成兩序列,時間為一常數,時間複雜度o(1).解決問題時間是兩個遞迴式,把一個規模為n的問題分成兩個規模分別為n/2的子問題,時間為2T(n/2).合併時間複雜度為o(n)。總時間T(n)=2T(n/2)+o(n).這個遞迴式可以用遞迴樹來解,其解是o(nlogn).此外在最壞、最佳、平均情況下歸併排序時間複雜度均為o(nlogn).從合併過程中可以看出合併排序穩定。
用遞迴樹的方法解遞迴式T(n)=2T(n/2)+o(n):假設解決最後的子問題用時為常數c,則對於n個待排序記錄來說整個問題的規模為cn。
從這個遞迴樹可以看出,第一層時間代價為cn,第二層時間代價為cn/2+cn/2=cn.....每一層代價都是cn,總共有logn+1層。所以總的時間代價為cn*(logn+1).時間複雜度是o(nlogn).
3、附錄
參考書籍: 《演算法導論》