標籤:排序演算法 java 選擇
排序可分為兩種:內排序和外排序。在排序過程中,全部記錄存放在記憶體,稱為內排序;如果排序過程中需要使用外存,則成為外排序。
內排序有以下幾類:
- 插入類排序:直接插入排序、二分法(折半)插入排序、希爾(縮小增量)排序
- 選擇類排序:簡單選擇排序、堆排序
- 交換類排序:冒泡排序、快速排序、三路劃分的快速排序
- 歸併類排序:二路歸併排序
- 基數類排序:MSD基數排序、LSD基數排序
各種內部排序演算法的比較
直接插入排序、氣泡排序和簡單選擇排序是基本的排序方法。它們平均情況下的時間複雜度都是O(n2),它們的實現也都非常簡單。
直接插入排序對於規模很小的元素序列(n≤25),可以說是非常有效。它的時間複雜度與待排序元素序列的初始排列有關。在最好情況下,直接插入排序只需要n-1次比較就可以完成,而且不需要交換。在平均情況下和最差情況下,直接插入排序的比較和交換都是O(n2)。
改進的冒泡排序在最好情況下只需要一趟冒泡過程就可以完成,此時也只需要n-1次比較就可以了。
簡單選擇排序的排序碼比較次數與待排序元素序列的初始排列無關,其比較次數總是O(n2),但元素移動次數則與待排序元素序列的初始排列有關,最好情況下一次也不移動,最差情況下元素移動次數不超過3(n-1)次。
從記憶體複雜度來看,這三種基本的排序方法除了一個輔助元素外,都不需要其他額外的記憶體空間。從穩定性來看,直接插入排序和冒泡排序都是穩定的,但簡單選擇排序不是。它們主要用於元素個數n不是很大(<10K)的情形。
快速排序是最通用的高效的內部排序演算法,平均情況下的時間複雜度為O(nlog2n),一般情況下所需要的額外記憶體也是O(log2n)。但是快速排序是個不穩定的演算法。並且在有些情況下可能會退化(例如元素序列已經有序時),時間複雜度會增加到O(n2),空間複雜度也會增加到O(n)。改進的快速排序演算法,即三路劃分的快速排序演算法,能夠有效地避免最壞情況的發生。
堆排序也是一種高效的內部排序演算法,它的時間複雜度是O(nlog2n),而且沒有什麼最壞情況會導致堆排序的運行明顯變慢,並且堆排序基本不需要額外的記憶體空間。但堆排序不太可能提供比快速排序更好的平均效能。堆排序是一種不穩定的排序演算法。
歸併排序也只一個重要的高效排序演算法它的效能與輸入元素序列無關,時間複雜度總是O(nlog2n)。但它的主要缺點是直接執行時需要O(n)的附加記憶體空間,雖然有方法可以克服這個缺點,但是其代價是演算法會很複雜且時間複雜度會增加,因此在實際應用中一般不值得這樣做。歸併排序演算法是一種穩定的高效排序演算法。
快速排序、堆排序和歸併排序適合於元素個數n很大的情況。
希爾排序的時間複雜度介於基本排序演算法和高效排序演算法之間,雖然迄今為止對其效能的分析還是不精確的,但是希爾排序代碼簡單,基本不需要什麼額外記憶體,空間複雜度低。希爾排序是一種不穩定的排序演算法。對於中等規模的元素序列(n≤1000),希爾排序是一種很好的選擇。
基數排序是一種相對特殊的排序演算法,這類演算法不僅是對元素序列的排序碼進行比較,更重要的是它們對排序碼的不同部分進行處理和比較。雖然基數排序具有線性增長的時間複雜度,但是由於在常規編程環境中,關鍵字索引統計程式內部迴圈中包含大量操作,其數目比快速排序或者歸併排序演算法的內部迴圈多得多。所以基數排序的線性時間開銷實際上不比快速排序的時間開銷小很多。並且由於基數排序基於的排序碼抽取演算法受到作業系統和排序元素的影響,其適應性遠不如普通的比較和交換操作。因此在實際工作中,常規的高效排序演算法如快速排序的應用要比基數排序廣泛得多。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
各種排序演算法分析及其Java實現