算法基礎之排序算法[圖文]

文章脈絡算法

        

算法編程

   什麼是算法?性能

    算法是解題方案的準確而完整的描述,是一系列解決問題的清晰指令,算法表明着用系統的方法描述解決問題的策略機制。 排序算法就是對排序的一種解決方案;而查找算法就是對查找的解決方案。spa

   算法用來幹什麼?.net

    提升計算機速度並節省存儲空間一直成爲編程人員努力的方向,排序操做成爲程序設計人員考慮的因素之一,排序方法選擇得當與否直接影響程序執行的速度和輔助存儲空間的佔有量,進而影響整個軟件的性能。設計

    此處省略2000字……指針

排序算法對象

    所謂排序就是把一組無序序列按照關鍵字有序的排列起來。在待排序的數據中,若是存在多個相同關鍵字,通過排序後這幾個相同關鍵字的相對次序不變,則該排序時穩定的;不然爲不穩定的,以下圖:blog

            

    如下不單獨說明都以正序排序爲例(從小到大)。排序

插入排序

    插入排序的基本思想是從待排序中拿出一個元素,而後逐個拿出一個元素,與當前元素比較,插入到合適的位置,直到所有插入完畢爲止。

    直接插入排序

    直接排序在插入第i個元素時,R1R2……Ri-1已經排好序,將第i個元素依次與R1Ri-1比較,找到合適位置。直接排序要進行n-1趟排序。

    以數字1-7打亂順序後排序爲例:

        希爾排序

    希爾排序時對直接插入排序的升級版,我認爲希爾排序的升級在於:先利用步長將元素分組,組內排序完畢後;再從新用步長分組,再排序,直到完整排序,實質是分組插入方法。

    仍然以被打亂的7個數字爲例(相同顏色連線爲一組):

選擇排序

    選擇排序的基本思想是從帶排序的元素中,選出最小的記錄,讓後順次排下去。

    直接選擇排序

    仍然以被打亂的7個數字爲例:

            

    堆排序

    堆排序的基本思想是先把全部元素按層次遍歷放到一棵徹底二叉樹中,這棵二叉樹須要知足:子節點值都大於父節點值(小頂堆),或子節點值都小於父節點值(大頂堆),步驟以下:

      1. 而後能夠知道這棵樹中根節點值最小(小頂堆)
      2. 編號最大的元素與根節點元素交換位置,交換位置後取出原根節點元素
      3. 重複12步驟

    仍然以被打亂的7個數字爲例:

    排出正確大頂堆:

    而後讓根節點位置與最大編號結點位置對調,並斷開原根節點與堆的聯繫,以下:

    從新對剩餘的樹按大頂堆排序:

    重複上面的步驟,獲得:

    按層次遍歷,便可獲得排序結果。

    從上面也能夠看出,按正序排列,須要先構建大頂堆;按逆序排列,須要小頂堆。一位堆排序構建初始堆須要的比較次數較多,因此堆排序不適合元素較少的排序。

交換排序

    交換排序的基本思想是兩兩進行比較,再根據比較結果決定是否交換位置,主要的交換排序有冒泡法和快速排序法。

    冒泡排序

    恰如其名,冒泡的意思就是假設有兩個氣泡,重量和待排序中的元素值相同,每次冒泡都讓最輕的一個元素向上(前)移動。

    仍然以被打亂的7個數字爲例:

    快速排序

    快速排序的基礎是分治法,即將問題分解爲若干個小可是結構與原問題結構相似的子問題,遞歸解決這些子問題,再將子問題的解組合爲原問題的解。

    仍然以被打亂的7個數字爲例,爲了更清楚顯示,咱們採用逆序排序:

    注意,在選定基準之後,須要左數第幾個和右數第幾個交替比較:按此例來講,是基準先與右數第一個比較,再與左數第一個比較,再與右數第二個比較……

    再在前四個元素和後兩個元素中選擇基準,再按上述步驟排序:

    由於例子比較簡單,因此兩次就完成排序。快速排序的時間主要是花費在劃分操做上,對長度爲k的區間進行劃分,共須要k-1次關鍵字比較。它是基於關鍵字比較的內部算法中最快的一種。

歸併排序

    歸併排序就是使用合併操做完成排序的算法,若是利用二路合併操做,則稱爲二路合併排序,它的過程是:

      1. 首先把待排序區間中的每一個元素都看做一個有序表經過兩兩合併,生n/2(向下取整)個長度爲2(最後一個表的長度可能小於2)的有序表,這也稱爲一趟合併
      2. 而後再將過n/2(向下取整)個有序表進行兩兩合併,生成比n/4(向下取整)個長度爲4的有序表;
      3. 如此循環直到獲得一個長度爲n的有序表,一般須要log2n趟,若是該值爲奇數,則爲log2n+1(向下取整)。

    仍然以被打亂的7個數字爲例:

歸併排序是穩定的排序,可使用順序存儲結構也可使用鏈表,歸併排序須要一個輔助量來暫存兩個有序子文件的歸併結果。

基數排序

    這個排序方法的基本思路上面幾種排序稍有區別,根據小學教的,一個3位數字的大小怎麼決定?有百位看百位,沒百位的看十位,沒十位的比個位。這種方法就是基於此的。

這種排序方法,上面用的「打亂的7個數字」就不合適了,從新選擇亂序數集合爲:{315,707,101,123,489,918,613},由於是正序排列,因此從個位開始比較。

    個位排序有什麼用,這不仍是一點關聯也沒有嗎?開始我也有這個疑問,想着爲何不是從百位開始排,那樣更一目瞭然。如今想一想即便按百位開始排,也是把幾個百位爲某個值的放到一塊兒,仍然不能夠一蹴而就,更況且,幾個無序數列,不知道一共有多少位。一樣,按個位開始排序的方法,就至關於先把個位相同的分爲一組,若是再按十位排序,須要遵循已經排好的個位序。

 

    繼續按百位排序:

       

 

    爲了減小元素移動次數,隊列能夠採用鏈式存儲分配,每一個隊列有兩個指針,分別指向隊頭和隊尾。

    這個方法思想雖然容易理解,可是由於是從個位開始排,與平常按高位開始排相逆,多少須要思惟的轉換,你們能夠比對從高位開始排序反過來想從個位排。

對比

各類排序方法之間複雜度與穩定性以下表:

    上述所講排序不僅是方法,更是思想,例如歸併排序:在如今你所處的圈內的值是最高的,若是和其餘圈子合併以後呢?呵呵說多了,理解這些排序算法,我以爲最重要的幾點是:排序的目的、排序對象、每種排序特有的思想,若是能把算法結合到生活當中,忘是忘不掉的。

轉自:http://blog.csdn.net/lidatgb/article/details/8044708

相關文章
相關標籤/搜索