常用排序算法原理總結

前面有篇文章總結了性能,同時強調了算法原理纔是最重要的,僅僅記住一些性能指標的數據,是沒有用的。這篇文章主要以較“精煉簡單”但是又“詳細囉嗦”的語言來描述算法實現的細節過程!注意:可能不適合初學者看,初學者應該先看算法書籍以及實現的源碼,然後再參考下文敘述來幫助理解算法實際的原理!本篇沒有實例代碼,請參看《大話數據結構》的C源碼和個人的github的java源碼鏈接!(《大話數據結構》java語言實現

一、簡單排序
1、冒泡:起始時,從最後一個數字開始逐個與前面的數字比較(小則替換,大則不替換),直至確定當前的索引號的位置;(外循環確定當前索引號,內循環執行冒泡比較)
  冒泡plus:添加一個標誌位,用來記錄上一次外循環比較的時候是否發生交換,如果沒發生交換,說明已經排序好了,以後的外循環排序就沒有必要了,所以直接跳出就可以了!

2、簡單選擇:起始時,規定當前外循環的索引號爲最小值,然後後續數字都和這個最小值比較,直到比較完後,確定新的最小值,然後才交換(注意比較的時候不交換);繼續循環,確定下一個索引號的最小值;(PS:其實就是找最小值然後插入0位,然後再找剩下的最小值(即第二最小)插入1位,依次類推,和冒泡不同的是,冒泡每次從後邊往前面比較而且都交換,然後“冒”上來!這個是從前往後比找到最小值最後才交換)

3、直接插入:起始時選擇i=2位置的記錄值作爲比較對象(i=0爲哨兵位)並緩存至i=0位,然後開始從i-1位->0位元素逐個與當前數據比較(已經緩存到0位了,其實也就是和0位比較),比它大則說明i-1位不應該在當前i位的左側,所以後移,直到遇到比它小或者等於(等於的時候比較到0位了)的則退出比較。此時空出的位置就是i=2記錄值的新位置,以此類推;
  直接插入plus:從倒數第二個開始比較,即首先取出n-1位,並緩存!從n-2->0位順序開始比較,比它大則後移,比它小則停止比較,把緩存的當前的數據插入到此時空出的位置,重新緩存當前比它小的數據,以此類推 !(PS:原理都是一樣的,但是從後往前比其實邏輯更好理解)

4、希爾排序:參見直接插入,只不過希爾排序不是-1的比較,而是-n的比較(PS:希爾排序也是插入排序,都是先緩存當前位數據!只不過希爾排序每次從-1位開始開始和當前位比較,然後步進爲-1向前進軍;希爾排序首先就從-n位開始當前位比較,然後步進爲-n向前進軍。二者都是遇到比它大的數字,然後大數字後移,當然後移的位置也是1位和n位的差別!還有就是n並不是一個定值,比如建議n=n/3+1,n初始值爲序列長,經過這個計算後纔是第一次用到的步進值!當序列遍歷到最後一個節點的時候(初始化從n+1開始遍歷),則再次計算n值)

二、高級排序:
5、堆排序:構造堆——首先把序列看成是一個層序遍歷的二叉樹,然後起始點默認是length/20,開始比較所在的根節點和子節點大小(共三個數字記錄),把最大的數字記錄交換爲當前根節點,然後依次類推變成一個大頂堆(假設length=9,則分別把(4,9)(3,9)(2,9)(1,9)變成大頂堆);排序——把堆低的數字記錄(末尾)和root節點交換,然後繼續構造剩餘數據記錄(即(1,8)(1,7)(1,6)…..)的大頂堆,以此類推直到最後排序完成。

6、歸併排序:拆分歸併——首先會把序列進行遞歸拆分,直到出現拆分過後當前棧內首位=末尾,則跳出循環繼續遞歸拆分上一個棧的另半邊序列,再跳出循環開始歸併比較!在跳出循環進入下一輪左拆分、右拆分、歸併的步驟,直到最後比較完!排序——歸併思想很簡單,就是找到一個輔助空間(這裏是輔助數組),然後分別比較原來兩個序列當前位置的數字大小(默認都是首位),誰小誰就歸併到輔助數組內,然後派出下一個數組繼續比較(類似車輪戰),最後總有一個序列先把數字“派出來”完了,然後沒有被派出來完的數組直接把剩餘數組追加到輔助數組後面就行了!(注意歸併的時候,兩個序列已經是分別有序的了)
  歸併排序plus(非遞歸模式):上述遞歸實現拆分歸併比較難理解,而且會佔用較大的空間(空間複雜度是nlogn)!,所以建議使用非遞歸的方式來進行拆分和歸併!這個很好理解,首先選取1,2位比較然後歸併;3,4位比較,然後歸併……..,一輪下來將會出現兩兩有序(奇數會剩餘一個);在進行第二輪的兩兩歸併,將會出現四四有序,最後四四歸併,出現八八有序……..直到最後全部有序!(PS:非遞歸方式空間複雜度只有n,時間性能也有提升,所以性能更優,請優先使用!)

7、快速排序:樞軸值——起始時選擇首位數字記錄開始比較,然後從兩邊向中間遍歷,比它大的通過交換放在右邊,比它小的通過交換放在左邊(每次交換後,才把比較的“焦點”從一邊轉向另一邊,即兩邊向中間遍歷。所以並不是第一次比較左邊,第二次就比較右邊了,而是發生交換後才從左邊移向右邊),最後首位數字記錄值的索引號將發生改變這個索引號就是樞軸值;然後對低字表再次遞歸求樞軸值,對高字表再次遞歸求樞軸值(PS:很有前幾天二叉樹推導算法的遞歸思想)
  快速排序plus:三數取中——對首位、中間位、高位求樞軸值,最後確定變換後的首位數字記錄爲整個序列的樞軸值;樞軸值——把當前樞軸值的數字記錄備份到i=0位,由原來的交換改爲替換,當遍歷的時候發現替換的兩個數字記錄相等,則當前位置就是實際的樞軸值;然後排序

注:以上爲排序算法的原理性描述,期間涉及遞歸、循環等,尤其是索引號的確認(+1或者-1什麼的)以及跳出的條件需要實際編程調試。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章