排序比較與總結

2021-06-17 15:05:05 字數 3934 閱讀 4011

之前一共實現了6種比較常見的排序演算法,分別是:

選擇排序,插入排序,氣泡排序,歸併排序,快速排序,堆排序

效率:

衡量乙個演算法的效率包括空間和時間,有時候還要考慮穩定性。

前3種排序的方法效率較低,實現也比較簡單,適合規模比較小的排序,個人認為適合排序總量在10000以下的隨機數組。

後3種排序的方法效率較高,實現稍微複雜一點,但也還好,適合規模較大的排序。

時間方面,前3種排序的複雜度都是o(n^2),後3種排序的複雜度都是o(n*logn),即呈指數級減少(因為基本思路都是遞迴的方式分治)。當然了,這是平均情況。

空間方面,即是否需要額外的空間,只有歸併排序需要乙個陣列長度相同的空間來儲存排序的結果,即o(n)。快速排序的需要o(

log2n

)。其餘排序都不需要額外的空間。

穩定性方面,只有插入排序和歸併排序是穩定的。穩定性保證的是陣列中值相等的資料在排序時順序不變,這在純int型陣列時沒什麼意義,但如果是複雜資料結構的排序,如果改變了順序則可能影響資料結構中其他欄位的排序。

疑問:誰能告訴我為什麼快速排序的空間複雜度是o(

log2n)?

特點:

每種排序都有自己的特點,要不然也不會留傳了這麼久。以下是個人看法:

氣泡排序:比較sb,只適合教學,效率低,但易實現。但能保證穩定。

選擇排序:比氣泡排序好一點,好的地方是交換次數少了,但仍然很sb。而且不穩定。

插入排序:有點像打撲克牌時的排序,但插入時會讓陣列的移動變多,如果是鍊錶則效率很高。且能保證穩定。

歸併排序:典型地遞迴分治,缺點是需要額外的空間來儲存結果。但能保證穩定。

快速排序:跟歸併排序很像,但區別是歸併排序切分的中點是陣列索引,快速排序切分的中點是第乙個資料的值。相同的是,都要碰運氣。但不穩定。

堆排序:思路很特別,花了好幾個班車上的時間片,另外用了撲克牌演示每一步的過程才弄明白流程。但不穩定。

執行時間比較:

這裡就專門寫個測試程式來測試一下這6種排序演算法的執行時間倒底區別有多大。

隨機生成100,000個數:

const int n = 200000;

int o = 0;

int* genrandom()

return a;

}

systemtime starttime = ;

filetime startfiletime = ;

systemtime endtime= ;

filetime sendfiletime= ;

int _tmain(int argc, _tchar* argv)

依次得到的結果如下:

bubblesort:1分37秒818,是的,你沒看錯。。

selectionsort:12秒338。

insertsort:1分11秒23。

mergesort:1秒598

quicksort:0秒036

heapsort:0秒081

說多了都是淚....這才是100,000個數,假設要是千萬級的,差別就更大了,可能冒泡需要幾個小時。。而快速和堆排序都表現的相當優秀。

這也難怪快速排序叫做快速排序。

實現**:

以防我的**實現的有問題,影響了測試效果,特將**列與此,如果有不足之處請各位指教和指正:

//#include "stdafx.h"

#include "windows.h"

#include "time.h"

const int n = 100000;

int o = 0;

int* genrandom()

return a;

}void swap(int& a, int& b)

//small -> large

void selectionsort(int* ua)

o++;

} swap(ua[i], ua[nminindex] ); }}

//small -> large

void insertsort(int* ua)

} }

}//small -> large

void bubblesort(int* ua)

*/for (int j = 0; j < (n-i-1); j++)

o++;

} }

} void merge(int* ua, int nstart, int nmid, int nend)

for (int k = nstart; k <= nend; k++)

else if(j > nend)

else if( a[j] < a[i])

else

/*printf("round %d \r\n", k);

for (int k = nstart; k < nend; k++)

*/ }}

//small -> large

void mergesort(int* ua, int nstart, int nend)

int nmid = nstart + (nend - nstart) / 2;

mergesort(ua, nstart, nmid);

mergesort(ua, nmid+1, nend);

merge(ua, nstart, nmid, nend);

}int quickpartition(int* ua, int nstart, int nend)

} //找到右邊小於中點的值,記錄索引

while( ua[--j] > nflagvalue )

}//兩邊向中間靠攏的過程中相遇則退出

if( i >= j)

//交換兩邊的值

swap( ua[i], ua[j] );

} //將右邊最後乙個小於中點值的數與中點值交換位置,

//保證中點值的左邊都小於中點值,右邊都大於中點值

swap( ua[nstart], ua[j] );

//返回將右邊最後乙個小於中點值的數的索引,做為右邊部分的中點值。

return j;

}void quicksort(int* ua, int nstart, int nend)

int nmid = quickpartition(ua, nstart, nend);

quicksort(ua, nstart, nmid-1);

quicksort(ua, nmid+1, nend);

}void heapadjust(int* ua, int nstart, int nend)

} //如果父結點大於子節點,則退出,否則交換

if (ua[nstart] > ua[nmaxindex])

else

} /*for (int i = 0; i < n; i++)

printf("\r\n");*/

//printf("%d ", o++);

}void heapsort(int* ua, int nstart, int nend)

for (int i = nend-1; i > 0; i--) }

systemtime starttime = ;

filetime startfiletime = ;

systemtime endtime= ;

filetime sendfiletime= ;

int _tmain(int argc, _tchar* argv)

排序演算法的比較與總結

歸併 穩定,o nlogn 遞迴實現 大類排序方法 時間複雜度 空間複雜度 穩定性實現方法 備註交換法 冒泡法最差 平均都是o n 2 最好是o n 1穩定 n較小時較好 交換法雞尾酒冒泡法 最差 平均都是o n 2 最好是o n 1穩定 n較小時較好 交換法快速排序 平均o nlogn 最壞是o ...

氣泡排序改進與總結

5 改進的氣泡排序 從小到大排序 void bubblesort int array int n if 0 exchange return 如果某遍沒有交換,說明已經排序好。6 氣泡排序的穩定性 如果將array j 7 陣列的初始順序對冒泡的影響 如果初始陣列就是從小到大的順序,則氣泡排序的比較次...

快速排序 優化與總結

基礎快排 快排的基本框架就是下邊這樣。更魯棒一點的話,還需要考慮傳入的array是否是非法引數。此處優化 應當將陣列,打亂順序,如果陣列基本有序,快排的時間複雜度將退化到 應該在傳入sort之前就將陣列 shuffle。public static void sort int array,int lo...