排序算法

隨便配得圖哈!

排序算法經過了很長時間的演變,產生了很多種不同的方法。對于初學者來說,對它們進行整理便于理解記憶顯得很重要。每種算法都有它特定的使用場合,很難通用。因此,我們很有必要對所有常見的排序算法進行歸納。
我不喜歡死記硬背,我更偏向于弄清來龍去脈,理解性地記憶。比如下面這張圖,我們將圍繞這張圖來思考幾個問題。

常見的排序算法

上面的這張圖來自一個PPT。它概括了數據結構中的所有常見的排序算法。現在有以下幾個問題:
1、每個算法的思想是什么?
2、每個算法的穩定性怎樣?時間復雜度是多少?
3、在什么情況下,算法出現最好情況 or 最壞情況?
4、每種算法的具體實現又是怎樣的?
這個是排序算法里面最基本,也是最常考的問題。下面是我的小結。
一、直接插入排序(插入排序)。
1、算法的偽代碼(這樣便于理解):

 INSERTION-SORT (A, n)             A[1 . . n] 
 for j ←2 to n 
      do key ← A[ j] 
      i ← j – 1 
      while i > 0 and A[i] > key 
           do A[i+1] ← A[i] 
                i ← i – 1 
      A[i+1] = key

 2、思想:如下圖所示,每次選擇一個元素K插入到之前已排好序的部分A[1…i]中,插入過程中K依次由后向前與A[1…i]中的元素進行比較。若發現發現A[x]>=K,則將K插入到A[x]的后面,插入前需要移動元素。


 3、算法時間復雜度。  
    最好的情況下:正序有序(從小到大),這樣只需要比較n次,不需要移動。因此時間復雜度為O(n)  
    最壞的情況下:逆序有序,這樣每一個元素就需要比較n次,共有n個元素,因此實際復雜度為O(n-2)  
    平均情況下:O(n-2)

 4、穩定性。  
 理解性記憶比死記硬背要好。因此,我們來分析下。穩定性,就是有兩個相同的元素,排序先后的相對位置是否變化,主要用在排序時有多個排序規則的情況下。在插入排序中,K1是已排序部分中的元素,當K2和K1比較時,直接插到K1的后面(沒有必要插到K1的前面,這樣做還需要移動!!),因此,插入排序是穩定的。

 5、代碼(c版) blog.csdn.com/whuslei 
0_1306225543SnQ8.gif.png

二、希爾排序(插入排序)

 1、思想:希爾排序也是一種插入排序方法,實際上是一種分組插入方法。先取定一個小于n的整數d1作為第一個增量,把表的全部記錄分成d1個組,所有距離為d1的倍數的記錄放在同一個組中,在各組內進行直接插入排序;然后,取第二個增量d2(<d1),重復上述的分組和排序,直至所取的增量dt=1(dt<dt-1<…<d2<d1),即所有記錄放在同一組中進行直接插入排序為止。    
 例如:將 n 個記錄分成 d 個子序列: 
   { R[0],   R[d],     R[2d],…,     R[kd] } 
   { R[1],   R[1+d], R[1+2d],…,R[1+kd] } 
     … 
   { R[d-1],R[2d-1],R[3d-1],…,R[(k+1)d-1] }
0_1306225546mbOy.gif.png
 說明:d=5 時,先從A[d]開始向前插入,判斷A[d-d],然后A[d+1]與A[(d+1)-d]比較,如此類推,這一回合后將原序列分為d個組。<由后向前>
 2、時間復雜度。  
 最好情況:由于希爾排序的好壞和步長d的選擇有很多關系,因此,目前還沒有得出最好的步長如何選擇(現在有些比較好的選擇了,但不確定是否是最好的)。所以,不知道最好的情況下的算法時間復雜度。  
 最壞情況下:O(N*logN),最壞的情況下和平均情況下差不多。  
 平均情況下:O(N*logN)
 3、穩定性。  
 由于多次插入排序,我們知道一次插入排序是穩定的,不會改變相同元素的相對順序,但在不同的插入排序過程中,相同的元素可能在各自的插入排序中移動,最后其穩定性就會被打亂,所以shell排序是不穩定的。(有個猜測,方便記憶:一般來說,若存在不相鄰元素間交換,則很可能是不穩定的排序。)
 4、代碼(c版) 
0_130622554949B9.gif.png

三、冒泡排序(交換排序)

   1、基本思想:通過無序區中相鄰記錄關鍵字間的比較和位置的交換,使關鍵字最小的記錄如氣泡一般逐漸往上“漂浮”直至“水面”。 
    image      2、時間復雜度  
 最好情況下:正序有序,則只需要比較n次。故,為O(n)  
  最壞情況下:  逆序有序,則需要比較(n-1)+(n-2)+……+1,故,為O(N*N)
  3、穩定性  
  排序過程中只交換相鄰兩個元素的位置。因此,當兩個數相等時,是沒必要交換兩個數的位置的。所以,它們的相對位置并沒有改變,冒泡排序算法是穩定的!
  4、代碼(c版)      
0_1306225555B9Ab.gif.png

四、快速排序(交換排序)

 1、思想:它是由冒泡排序改進而來的。在待排序的n個記錄中任取一個記錄(通常取第一個記錄),把該記錄放入適當位置后,數據序列被此記錄劃分成兩部分。所有關鍵字比該記錄關鍵字小的記錄放置在前一部分,所有比它大的記錄放置在后一部分,并把該記錄排在這兩部分的中間(稱為該記錄歸位),這個過程稱作一趟快速排序。
0_1306225555QLgg.gif.png

說明:最核心的思想是將小的部分放在左邊,大的部分放到右邊,實現分割。

 2、算法復雜度  
  最好的情況下:因為每次都將序列分為兩個部分(一般二分都復雜度都和logN相關),故為 O(N*logN)  
  最壞的情況下:基本有序時,退化為冒泡排序,幾乎要比較N*N次,故為O(N*N)

  3、穩定性  
  由于每次都需要和中軸元素交換,因此原來的順序就可能被打亂。如序列為 5 3 3 4 3 8 9 10 11會將3的順序打亂。所以說,快速排序是不穩定的!
  4、代碼(c版) 
0_1306225559WGnG.gif.png

五、直接選擇排序(選擇排序)

  1、思想:首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續尋找最小元素,然后放到排序序列末尾。以此類推,直到所有元素均排序完畢。具體做法是:選擇最小的元素與未排序部分的首部交換,使得序列的前面為有序。  
  2、時間復雜度。 
  最好情況下:交換0次,但是每次都要找到最小的元素,因此大約必須遍歷N*N次,因此為O(N*N)。減少了交換次數! 
  最壞情況下,平均情況下:O(N*N)
  3、穩定性 
  由于每次都是選取未排序序列A中的最小元素x與A中的第一個元素交換,因此跨距離了,很可能破壞了元素間的相對位置,因此選擇排序是不穩定的!
  4、代碼(c版)
0_1306225562pyZQ.gif.png

六、堆排序

 1、思想:利用完全二叉樹中雙親節點和孩子節點之間的內在關系,在當前無序區中選擇關鍵字最大(或者最小)的記錄。也就是說,以最小堆為例,根節點為最小元素,較大的節點偏向于分布在堆底附近。 
2、算法復雜度 
     最壞情況下,接近于最差情況下:O(N*logN),因此它是一種效果不錯的排序算法。
  3、穩定性 
     堆排序需要不斷地調整堆,因此它是一種不穩定的排序!
  4、代碼(c版,看代碼后更容易理解!)      
0_1306225568lL88.gif.png

七、歸并排序

  1、思想:多次將兩個或兩個以上的有序表合并成一個新的有序表。 
  2、算法時間復雜度 
      最好的情況下:一趟歸并需要n次,總共需要logN次,因此為O(N*logN) 
      最壞的情況下,接近于平均情況下,為O(N*logN) 
      說明:對長度為n的文件,需進行logN 趟二路歸并,每趟歸并的時間為O(n),故其時間復雜度無論是在最好情況下還是在最壞情況下均是O(nlgn)。
  3、穩定性 
     歸并排序最大的特色就是它是一種穩定的排序算法。歸并過程中是不會改變元素的相對位置的。 
  4、缺點是,它需要O(n)的額外空間。但是很適合于多鏈表排序。 
  5、代碼(略)

八、基數排序

  1、思想:它是一種非比較排序。它是根據位的高低進行排序的,也就是先按個位排序,然后依據十位排序……以此類推。示例如下: 
  2、算法的時間復雜度 
   分配需要O(n),收集為O(r),其中r為分配后鏈表的個數,以r=10為例,則有0~9這樣10個鏈表來將原來的序列分類。而d,也就是位數(如最大的數是1234,位數是4,則d=4),即"分配-收集"的趟數。因此時間復雜度為O(d*(n+r))。
  3、穩定性 
      基數排序過程中不改變元素的相對位置,因此是穩定的!
  4、適用情況:如果有一個序列,知道數的范圍(比如1~1000),用快速排序或者堆排序,需要O(N*logN),但是如果采用基數排序,則可以達到O(4*(n+10))=O(n)的時間復雜度。算是這種情況下排序最快的!!
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容

  • 排序算法經過了很長時間的演變,產生了很多種不同的方法。對于初學者來說,對它們進行整理便于理解記憶顯得很重要。每種算...
    DNIX閱讀 1,780評論 0 2
  • 一. 寫在前面 要學習算法,“排序”是一個回避不了的重要話題,在分析完并查集算法和常用數據結構之后,今天我們終于可...
    Leesper閱讀 2,541評論 0 40
  • 概述 排序有內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部...
    蟻前閱讀 5,207評論 0 52
  • 概述:排序有內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部...
    每天刷兩次牙閱讀 3,737評論 0 15
  • 星期六休息,但是覺得比工作日事情還多,不提學習的事情,因為約定輪空。 昨天銘帥不舒服,貼了一個膏藥,還...
    指揮官閱讀 296評論 2 3