1. 程式人生 > >《關於排序,你應該知道的》

《關於排序,你應該知道的》

一、關於排序的幾個概念 (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)當原表有序或基本有序時,直接插入排序和氣泡排序將大大減少比較次數和移動元素的次數,時間複雜度可降至On);而快速排序則相反,當原表基本有序時,將退化為氣泡排序,時間複雜度提高為O(n2)原表是否有序,對直接選擇排序、堆排序、歸併排序和基數排序的時間複雜度影響不大。 (8)一般不使用或不直接使用傳統的氣泡排序。

相關推薦

《關於排序應該知道的》

一、關於排序的幾個概念 (1)資料表:待排序資料元素的有限集合。 (2)排序碼(也常稱為“關鍵字”):資料元素中通常不止含有一個屬性域(即資料成員),選定其中一個屬性域作為排序的依據。該域稱為

關於 Token應該知道的十件事

敏感信息 you load 冒充 tro hex 服務器 xhr cors 轉自:http://ju.outofmemory.cn/entry/134189 原文是一篇很好的講述 Token 在 Web 應用中使用的文章,而這是我和 Special 合作翻譯的譯文。 1.

做網站SEO優化這些網絡引流方法應該知道

尋求 可能 垃圾郵件 百度搜 如果 什麽 網站鏈接 很快 建立 對於網站SEO優化來說,網站流量的重要性不言而喻!國內的站長平臺工具通過用網站流量來衡量一個網站的權重,當你的網站流量很高的時候,同時會影響你網站的權重,進而影響你網站SEO優化排名。所以說流量對於一個網站的意

Select 使用不當引發的core應該知道

retcode 代碼 async fetch sse com 基礎 -a cnblogs 排查一個死機問題,搞了好幾天時間,最終確定原因;最終確定問題原因,在此分享一下; 第一步:常規根據core文件查看棧信息,gdb –c core xxxx 如下rip不正確,指令地址錯

關於首個受監管的穩定幣GUSD應該知道這些真相

今天早上,美國交易所 Gemini 和另外一個區塊鏈創業公司 Paxos 同時獲得了美國紐約金融服務局的批准,可以在受政府監管的情況下發行錨定美元的數字加密貨幣 GUSD 和 PAX。這種與美元掛鉤而且可以與美元進行直接兌換的數字加密貨幣在區塊鏈行業中有不少先例,比如我們熟悉

看完這篇應該知道什麼是Linux了~

Linux上的檔案系統一般來說就是EXT2或EXT3,但這篇文章並不準備一上來就直接講它們,而希望結合Linux作業系統並從檔案系統建立的基礎——硬碟開始,一步步認識Linux的檔案系統。 1.機械硬碟的物理儲存機制 現代計算機大部分檔案儲存功能都是由機械硬碟這種裝置

2019Java依然免費應該知道的事實真相不要被誤導--技術領導必讀

     2019年關於Java是否免費,一直存在誤解,國內新聞斷章取義,搞錯概念,誤導開發者。 作為企業的技術領導應該弄清楚關鍵的概念,避免被誤導。      國內一直謠傳Java2019年1月1號收費,今天都2號了,使用Java的企業運轉一切正

當問起執行緒池(Java中的ThreadPoolExecutor類)應該知道的基礎知識點

執行緒池 執行緒池是一種多執行緒處理形式,處理過程中將任務新增到佇列,然後在建立執行緒後自動啟動這些任務。執行緒池執行緒都是後臺執行緒。每個執行緒都使用預設的堆疊大小,以預設的優先順序執行,並處於多執行緒單元中。如果某個執行緒在託管程式碼中空閒(如正在等待某個事件),則執行緒池將插入另一個輔助執

當面試官問執行緒池時應該知道些什麼?

Java面試中,執行緒池也算是一個高頻的問題,其實就JDK原始碼來看執行緒池這一塊的實現程式碼應該算是寫的清晰易懂的,通過這篇文章,我們就來盤點一下執行緒池的知識點。 本文基於JDK1.8原始碼進行分析 首先看下執行緒池建構函式: public ThreadP

Activity生命週期的回撥應該知道得更多!--Android原始碼剖析(上)

private class ApplicationThread extends ApplicationThreadNative { //... public final void schedulePauseActivity(IBinder token, boolean finished,

安卓Service生命週期應該知道的都在這裡

如有轉載,請申明: Service是安卓的四大元件之一。它是一個沒有介面的元件,且優先順序大於後臺程序。 瞭解它的生命週期很有必要。 Service啟動的分類 啟動服務: 通過startService啟動的服務稱為啟動服務 繫結啟動服務: 通過bindSe

JAVA最起碼應該知道這些!

馬老師說過,員工的離職原因很多,只有兩點最真實: 錢,沒給到位 心,受委屈了 當然,我是想換個平臺,換個方向,想清楚為什麼要跳槽,如果真的要跳槽,想要拿到一個理想的offer,除了運氣,基本功也要足夠的紮實,希望下面的面試經驗能給你們能夠提供一些幫助。 專案經驗 面試官在一

用友雲開發者中心應該知道的那些事

bcb 過程 自定義環境 bfd 生產環境 log 灰度 查找 了解 2018開發者中心產品不斷進行架構升級優化,同時也在不斷完善產品能力,目前已支撐內部大量雲產品的運行,下面給大家介紹一下新增的幾大能力:一、一體化的計算資源管理1.提供資源池使用率看板,資源池的內存分配和

關於微軟Silverlight應該知道的10件事

對於任何成長中的企業來說,設計一個合適的網站是一件非常重要的事情,但是如何讓你的網站具有富網際網路應用程式(Rich Internet Applications,RIA)的體驗卻不是那麼簡單。為了在這方面為開發者減輕負擔,微軟最近推出了Silverlight——這是一個針對W

Activity生命週期的回撥應該知道得更多!--Android原始碼剖析(下)

private void handleBindApplication(AppBindData data) { mBoundApplication = data; mConfiguration = new Configuration(data.co

現在寫 PHP應該知道這些

轉載自:http://0x1.im/blog/php/php-now-you-shoud-know.html 首先你應該是在用 PHP 5.3 以上的版本,如果 PHP 版本在這之下,是時候該升級了。我建議如果有條件,最好使用最新的版本。 你應該看過 PHP The Ri

想要學習python應該知道的內容是啥?

ray mark 技術 程序 智能 四種 領域 ofo 第一個 Python具有豐富和強大的庫。它常被昵稱為膠水語言,能夠把用其他語言制作的各種模塊(尤其是C/C++)很輕松地聯結在一起。在學習Python之前,我們應該知道這些內容: 它是一種面向對象的解釋型計算機程序設計

程式設計師應該知道的資料結構之跳錶

跳錶的原理 跳錶也叫跳躍表,是一種動態的資料結構。如果我們需要在有序連結串列中進行查詢某個值,需要遍歷整個連結串列,二分查詢對連結串列不支援,二分查詢的底層要求為陣列,遍歷整個連結串列的時間複雜度為O(n)。我們可以把連結串列改造成B樹、紅黑樹、AVL樹等資料結構來提升查詢效率,但是B樹、紅黑樹、AVL樹這些

程式設計師應該知道的資料結構之雜湊表

雜湊表簡介 雜湊表也叫散列表,雜湊表是一種資料結構,它提供了快速的插入操作和查詢操作,無論雜湊表總中有多少條資料,插入和查詢的時間複雜度都是為O(1),因為雜湊表的查詢速度非常快,所以在很多程式中都有使用雜湊表,例如拼音檢查器。 雜湊表也有自己的缺點,雜湊表是基於陣列的,我們知道陣列建立後擴容成本比較高,所以

程式設計師應該知道的資料結構之棧

資料結構中的棧不要與 Java 中的棧混淆,他們倆不是一回事,資料結構中的棧是一種受限制的線性表,棧具有先進後出、後進先出的特點,因為棧只允許訪問最後一個數據項,即最後插入的資料項。也許你會有疑問,棧既然有這麼多限制,為什麼不用陣列或者連結串列而使用棧?在開發中,我們有特定的場景,根據特定的場景去選用資料結構