1. 程式人生 > >9種常見內部排序演算法的效能比較

9種常見內部排序演算法的效能比較

       在寫完這9種常見的內部排序演算法後總覺得需要把它們拿出來好好比較一番,看看各個演算法的效能優劣。

       我們先來看看這九種排序演算法的時間複雜度、空間複雜度和穩定性:


 看完了各個排序演算法的理論效能後,再來看一看在實踐上的效能。

       在程式裡,隨機數的範圍為0~49999999;進行10次外迴圈,每一趟外迴圈裡生成一個隨機陣列,陣列的大小逐趟遞增({50000, 100000, 500000, 1000000, 5000000, 10000000, 10000000, 50000000, 100000000, 500000000});在內迴圈裡利用各個排序演算法的函式對外迴圈裡生成的陣列進行排序,內迴圈執行15趟,然後記錄下每一趟裡每個演算法所花費的時間,算出這15趟的平均花費的時間(ms)。

       最後執行程式,得出以下的結果:

       其中,

       qsort:C函式庫自帶的排序函式qsort;

       quickSort:自己實現的快速排序;

       countSort:自己實現的計數排序(沒有考慮空間利用率和負數的版本);

       heapSort:自己實現的堆排序;

       shellSort:自己實現的希爾排序;

       mergeSort:自己實現的二路歸併排序;

       radixSort:自己實現的鏈式基數排序;

       insertSort2:優化後的插入排序;

       selectSort:自己實現的選擇排序;

       bubbleSort2:自己實現的經過簡單優化的氣泡排序。

       由於冒泡、插入和選擇排序在待排序元素數量增長的情況下呈平方關係增長,所以當待排序元素個數大於1000000後就去除了這三種排序演算法的比較了。


       很不幸,在陣列大小為500000000的時候,程式被無情的Kill了,估計是計數排序消耗太多的記憶體了。


       從以上結果可以看出隨著待排序元素個數的增加,各個 排序演算法所花費的時間也隨之增加,但是各個演算法在時間增加的幅度上卻有著不小的差別:

       由於,此次實驗中都是用C語言自帶的隨機數產生器,所以基本上可以認為產生的陣列是隨機的,進而可以知道此次比較主要是針對各個排序演算法在平均情況下的時間效能。

       首先來看看第一張圖片的那三個平均時間複雜度O(n2)的排序演算法(氣泡排序、插入排序和選擇排序),可以從第一張圖片中看出當陣列大小從50000增長到100000時(大小變為原來的2倍),排序所花費的時間變為原來的4倍(大約);但陣列大小從50000增長到500000時(大小變為原來的10倍),排序所花費的時間變為原來的100倍!大小和時間的關係基本上是平方關係。

       我們再來看看,那三個平均時間複雜度為O(nlgn)的排序演算法(快速排序、歸併排序和堆排序),其中對於快速排序和堆排序,當陣列從10000000增長到100000000(大小便為原來的10倍),排序所花費的時間變為原來的15倍到16倍(大約);當陣列從1000000增長到10000000時(大小變為原來的10倍),排序所花費的時間變為原來的15倍到16倍(大約);大小和時間的關係基本上是(1/2)n*lgn的關係。對於歸併排序,當陣列大小從1000000增長到10000000時(大小變為原來的10倍),排序所花費的時間變為原來的11.7倍;當陣列大小從10000000增長到100000000時(大小變為原來的10倍),排序所花費的時間變為原來的11.2倍;大小和時間的關係基本上是(1/3)n*lgn的關係。

       最後我們來看看,那兩個平均時間複雜度為常數時間的演算法(基數排序和計數排序),其中對於基數排序,排序時間的增長倍數和陣列大小增長倍數基本相當,滿足線性關係;對於計數排序,剛開始排序時間的增長比陣列大小的增長要來的小一些,但是當陣列大小增長到10000000以後排序時間的增長倍數和陣列大小的增長倍數基本相當,滿足線性關係。

       我的測試方法可能會有一定的侷限性,但是也能從這次測試中看出各個排序演算法的實際效能了。

       還有就是,原本是想用-O3的編譯優化選項,可是用這種方法生成的檔案在執行時會丟擲異常,導致程式終止,現在還不知是什麼原因.......

       下面是我的電腦的基本配置資訊:

       電腦的基本配置