一、關於排序的幾個概念
(1)數據表:待排序數據元素的有限集合。
(2)排序碼(也常稱爲“關鍵字”):數據元素中通常不止含有一個屬性域(即數據成員),選定其中一個屬性域作爲排序的依據。該域稱爲排序碼。
(3)主排序碼:數據表中各個數據元素的排序碼互不相同,這種排序碼爲主排序碼。
(如果按照主排序碼進行排序,排序結果是唯一的)
(4)次排序碼:數據表中有些數據元素的排序碼相同,這種排序碼爲次排序碼。
(如果按照次排序碼進行排序,排序結果不是唯一的)
二、什麼是排序
(1)“通俗”的定義:
排序就是將一組雜亂無章的數據按一定的規律順序排列好。
(2)精確定義:
設含有n個元素的序列爲R[0], R[1],
..., R[n-2], R[n-1],其相應的排序碼序列爲K[0],
K[1], ..., K[n-2],
K[n-1]。排序,就是確定n個數字0,1,...,n-1的一種排列p[0],
p[1], ..., p[n-2],
p[n-1],使得各個排序碼滿足如下的非遞減關係(或非遞增關係):
K[p[0]] <= K[p[1]]<=
...<= K[p[n-2]]<= K[p[n-1]]或
K[p[0]] >= K[p[1]]>=
... >= K[p[n-2]]>= K[p[n-1]]
三、排序算法的分類(分類依據:數據元素是否完全在內存中)
(1)內部排序:內部排序是指排序期間數據元素全部存放在內存中的排序。(適合於不太大的元素序列)
(內部排序的過程是一個逐步擴大記錄的有序序列長度的過程。)
(2)外部排序:外部排序指的是大文件的排序,即待排序的記錄存儲在外部存儲器上,待排序的文件無法一次裝入內存,需要在內存和外部存儲器之間進行多次數據交換,以達到排序整個文件的目的。
(外部排序中最常用的算法是多路歸併排序,即將原文件分解成多個能夠一次性裝入內存的部分,然後分別把每一部分調入內存完成排序)
四、排序算法的分類(分類依據:數據元素的物理位置在排序過程中是否改變)
(1)靜態排序:通過修改數據元素的指針,而各個數據元素的物理位置不變化來排序。
(2)動態排序:通過改變數據元素的物理位置來排序。
五、排序算法的分類(分類依據:算法的穩定性)
(1)穩定的排序算法:若存在多個具有相同排序碼的記錄,經過排序之後,這些記錄的相對次序仍然保持不變,則這種排序算法稱爲穩定的排序算法。
(2)不穩定的排序算法:若存在多個具有相同排序碼的記錄,經過排序之後,這些記錄的相對次序發生改變,則這種排序算法稱爲不穩定的排序算法。
六、排序算法的分類(分類依據:平均時間複雜度)
(1)平方階 O(n2):
一般稱爲簡單排序,如直接插入排序,選擇排序,冒泡排序。
(2)線性對數階 O(nlgn):
如快速排序,堆排序,歸併排序。
(3)O(n1+ԑ)[其中0<ԑ<1]:
如希爾排序。
(4)O(n):
如桶排序,基數排序。
七、各種常見排序算法的時間複雜度和空間複雜度(及穩定性)
八、時間複雜度函數的增長情況
九、根據以下因素並結合實際選擇合適的排序算法
(1)待排序的元素個數
(2)元素本身數據量的大小,也就是元素中除關鍵字外的其他信息量的大小
(3)關鍵字的結構及其分佈情況
(4)對排序穩定性的要求
(5)語言工具的條件
(6)所用的存儲結構
(7)時間複雜度
(8)(輔助)空間複雜度
十、各種常見排序算法小結
(1)直接插入排序:
1、算法運行時間與待排序元素的原始排列順序有關。
2、對於規模很小的待排序元素序列(n<=25)非常有效。
3、主要用於待排序元素個數不是很大(<10k)的情況。
(2)折半插入排序(二分法插入排序):
1、 折半搜索比順序搜索快,故在平均性能上折半插入排序快於直接插入排序。
2、當待排序元素已按排序碼排好序或接近有序時,直接插入排序比折半插入排序執行的排序碼比較次數要少。
3、折半插入排序的元素移動次數與直接插入排序相同,且都與待排序元素的原始排列順序有關。
(3)希爾排序(Shell排序、縮小增量排序):
1、對於中等規模的待排序元素序列(n<=1000),希爾排序有很高的效率。
2、希爾排序的時間複雜度分析很難,排序碼的比較次數與元素移動次數依賴於“增量因子序列”的選取,特定情況下可以準確估算出排序碼的比較次數和元素的移動次數。目前還沒有人給出選取最好的增量因子序列的方法。增量因子序列可以有各種取法,有取奇數的,也有取質數的,但需要注意:增量因子中除1
外沒有公因子,且最後一個增量因子必須爲1。
(4)冒泡排序(起泡排序):
1、改進的冒泡排序算法在最好情況下對於n個元素的排序只需一趟冒泡過程就可以完成,此時只需n-1次比較操作。
2、主要用於待排序元素個數不是很大(<10k)的情況。
(5)快速排序(分區排序):
1、是目前應用最廣泛的排序算法,也是最通用的高效的內部排序算法。
2、快速排序在空間上只使用一個小的輔助棧,內部循環很小,容易實現。
3、待排序元素個數n,當n較大時,在平均情況下快速排序是“快速”的,但當n很小時,快速排序一般慢於其他簡單排序方法。
4、適用於待排序元素個數n很大的情況。
5、當待排序的元素是隨機分佈時,快速排序的平均時間最短。
6、當待排序元素序列有序或接近有序時,快速排序反而退化爲冒泡排序。爲改進之,通常以“三者取中法”來選取基準記錄,即選取排序區間的兩個端點與中點這三個元素的排序碼中的中間值做爲基準記錄。
(6)歸併排序:
1、算法運行時間與待排序元素的原始排列順序無關,每次劃分產生的兩個子序列的長度基本相同,故其最好、最壞和平均時間複雜度都是O(nlgn)。
2、主要缺點是它需要一個與待排序元素數組一樣大的輔助數組空間,需要O(n)的附加內存空間。雖有方法克服這個缺點,但其代價是會使算法變得很複雜且時間複雜度會增加,故實際應用中一般不提倡這樣做。
3、適用於待排序元素個數n很大的情況。
(7)直接選擇排序:
1、直接選擇排序的排序碼比較次數與待排序元素的原始排列順序無關,元素的移動次數與待排序元素的原始排列順序有關。
2、相對於其他排序算法,待排序元素的原始排列順序(有序性)對於直接選擇排序的運行時間影響不大。因爲從未排序部分的元素中選擇出最小元素的每步操作過程,沒有對下一步要找的最小元素的位置給出相關信息。
3、直接選擇排序對於已排好序、接近有序、隨機排列的待排序元素序列所花時間基本相同,故執行時間比較固定。
4、直接選擇排序對於一種元素序列有較好的效率----元素規模很大,而排序碼較小的元素序列。因爲對這種序列進行排序,移動操作所花費的時間遠大於比較操作所花費的時間,而其他排序算法的移動操作次數都比直接選擇排序大得多。
5、主要用於待排序元素個數不是很大(<10k)的情況。
(8)錦標賽排序(樹形選擇排序):
1、克服了直接選擇排序中的缺點,已經不是像直接選擇排序那樣經常把前一趟已經做過的比較又重新做了一遍,而是改成將前一趟比較的結果保留了起來,供後一趟的比較操作使用。
(9)堆排序:
1、是一種高效的內部排序算法,沒有什麼最壞情況會導致堆排序的運行時間明顯變慢,基本不需要額外的空間。但它不大可能提供比快速排序更好的平均性能。
2、適用於待排序元素個數n很大的情況。
(10)桶排序(箱排序):
1、缺點是:空間複雜度比較高,需要的額外開銷大。排序中有兩個數組的空間開銷,一個存放待排序數組,一個是所謂的桶;其次,待排序的元素都要在一定的範圍內。
(11)基數排序:
1、它不僅對元素序列的排序碼進行比較,還對排序碼的不同部分進行處理和比較,雖然其時間複雜度爲線性增長,但由於在常規的編程環境中,關鍵字索引統計程序內部循環中包含大量操作,其數目比快速排序或歸併排序的內部循環要多得多,故基數排序的線性時間開銷實際上不比快速排序的時間開銷小很多。而且由於基數排序基於的排序碼抽取算法受到操作系統和排序元素的影響,導致其適應性不及普通的比較和交換操作。
2、在硬件環境、編程環境和輸入元素序列滿足一定條件時,基數排序可以達到很高的效率。
3、考慮到基數排序過程中使用額外的計數和額外的存儲空間(與待排序元素序列規模相同的存儲空間和與基數數目相等的一系列計數器),基數排序不適用於規模很小的待排序元素序列。
4、它的侷限性:排序碼可分解;元素的排序碼位數較少,如果密集更好;如果排序碼是數字,最好是無符號的,否則將增加相應的映射複雜度,可先將其正負分開排序。
十一、不同排序算法的選擇策略
(1)簡單排序中直接插入最好,快速排序最快,當文件爲正序時,直接插入和冒泡均最佳。
(2)當元素個數n較小時(如n≤50),可選用直接插入排序、直接選擇排序。
(3)當文件初始狀態基本有序(指正序),可選用直接插入排序、冒泡排序、隨機的快速排序。
(4)當元素個數n較大時,可選用時間複雜度爲O(nlgn)的排序方法:快速排序,堆排序,歸併排序。
(5)堆排序(不穩定)所需的輔助空間少於快速排序,並且不會出現快速排序可能出現的最壞情況。
(6)通常可以將歸併排序和直接插入排序結合在一起使用。先利用直接插入排序求得若干個較長的有序子序列,然後再兩兩歸併之。因爲直接插入排序是穩定的,原本的歸併排序也是穩定的,所以改進後的歸併排序仍是穩定的。
(7)當原表有序或基本有序時,直接插入排序和冒泡排序將大大減少比較次數和移動元素的次數,時間複雜度可降至O(n);而快速排序則相反,當原表基本有序時,將退化爲冒泡排序,時間複雜度提高爲O(n2);原表是否有序,對直接選擇排序、堆排序、歸併排序和基數排序的時間複雜度影響不大。
(8)一般不使用或不直接使用傳統的冒泡排序。
以上資料一些整合自: