1. 程式人生 > >內部排序和外部排序小結

內部排序和外部排序小結

一、內部排序的比較:

1、從時間複雜度來看:

簡單選擇排序、直接插入排序和氣泡排序的平均複雜度都為 O(n2),並且實現過程也較為簡單,但是直接插入排序和氣泡排序在最好的情況下時間複雜度可以達到 O(n),而簡單選擇排序則與序列的初始狀態無關。

希爾排序作為插入排序的擴充套件,對較大規模的排序都可以達到很高的效率,但是目前未得出其精確的漸近時間。

堆排序是利用一種稱為堆的資料結構,可以線上性時間內完成建堆,並且在 O(nlogn)內完成排序過程。

快速排序是基於分治的思想,雖然最壞的情況下快排的時間複雜度會到達 O(n2),但快速排序的平均效能可以達到 O(nlogn),在實際應用中常常優於其他的演算法。

歸併排序同樣是基於分治的思想,但由於其分割子序列與初始序列的排序無關,因此它的最好、最壞和平均時間複雜度均為 O(nlogn)。

2、從空間複雜度來說:

簡單選擇排序、插入排序、氣泡排序和希爾排序、堆排序都僅要藉助常數個輔助空間。

快速排序在空間上只使用一個小的輔助棧,用於實現遞迴,平均情況下大小為 O(logn),當然在最壞的情況下可能會增長到 O(n)。

二路歸併排序在合併操作中需要藉助較多的輔助空間用於元素複製,大小為O(n),雖然有方法可以克服這個缺點,但是其代價是演算法會很複雜而且時間複雜度會增加。

3、從穩定性來看:

直接插入排序、氣泡排序、歸併排序和基數排序都是穩定的排序演算法,而簡單選擇排序、快速排序、希爾排序和堆排序都是不穩定的排序方法。

 氣泡排序和堆排序在每次迴圈後都能產生當前的最大值或者最小值,而快速排序依次循壞就確定一個元素的最終位置。

由於希爾排序的時間複雜度依賴於增量函式,所以這裡無法準確的給出時間複雜度

    演算法種類                               時間複雜度          空間複雜度           是否穩定
   最好情況      平均情況    最壞情況
直接插入排序 O(n) O(n2) O(n2) O(1)
氣泡排序 O(n) O(n2) O(n2) O(1)
簡單選擇排序 O(n2) O(n2) O(n2) O(1)  否
希爾排序 O(n2) O(n1.3) O(1)  否
快速排序 O(nlogn) O(nlogn) O(n2) O(nlogn)  否
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1)  否
2-路歸併排序 O(nlogn) O(nlogn) O(nlogn) O(n)  是
基數排序 O(d(n+r)) O(d(n+r)) O(d(n+r)) O(r)  是

排序演算法小結:

1、若n較小(n<=50),則可以採用直接插入排序或者簡單選擇排序。由於直接插入排序所需的記錄移動操作較簡單選擇排序多,因而當記錄本身資訊量較大時,用簡單選擇排序較好。

2、若檔案的初始狀態已按關鍵字基本有序,則選擇直接插入或者氣泡排序為宜。

3、若n較大,則應採用時間複雜度為O(nlogn)的排序方法:快速排序、堆排序或歸併排序。快排被認為目前基於比較的內部排序法中最好的方法,當待排序的關鍵字是隨機分佈時,快速排序的平均時間最短。

堆排序所需的輔助空間少於快排,並且不會出現快排可能出現的最壞情況,這兩種排序都是不穩定的。若要求排序穩定且時間複雜度為O(nlogn),則可以選擇歸排序。

4、若n很大,記錄的關鍵字位數較少且可以分解時,採用基數排序較好。

5、當記錄本身資訊量較大時,為避免耗費大量的時間移動記錄。可用連結串列作為儲存結構。

二、外部排序

在記憶體中進行的排序稱為內部排序,而在許多實際應用中,經常需要對大檔案進行排序,因為檔案中的記錄很多,資訊量龐大,無法將整個檔案拷貝進記憶體進行排序。因此,需要將帶排序的記錄儲存在外存上,排序時再把資料一部分一部分的調入記憶體進行排序,在排序中需要多次進行內外存的互動,對外存檔案中的記錄進行排序後的結果仍然被放到原有檔案中。這種排序方法就稱外部排序。

由於外存裝置的不同,外部排序通常分為磁碟檔案排序和磁帶檔案排序。磁碟是直接存取裝置,磁帶是順序存取裝置。

檔案通常是按塊儲存在磁碟上,作業系統也是按塊對磁碟上的資訊進行讀寫的。因為磁碟讀寫的機械運動所需的時間遠遠超過記憶體計算的時間。因此,在外部排序過程中的時間代價主要考慮訪問磁碟的次數,即i/o次數。

外部排序通常採用歸併排序:它包括兩個相對獨立的階段:首先,根據記憶體快取區的大小,將外存上含有n個記錄的檔案分割成若干長度為 h 的子檔案,依次的讀入記憶體並利用有效的內部排序方法對他們進行排序,並將排序後得到的有序子檔案重新寫回外存,通常稱這些有序子檔案為歸併段或者順串。

然後,對這些歸併段進行逐趟歸併,使得歸併段(有序的子檔案)逐漸由小到大,直至得到整個有序檔案為止。

之後還可以採用多路平衡歸併和敗者樹,置換-選擇排序,最佳歸併樹進行處理,這裡就不一一展開了。