標籤:排序 遞迴 穩定性 時間效能
渾淪吞棗的過了一遍資料結構,今天把最後一章排序的內容結束。大概實現了一個星期看完的想法,當然不是為了求速度,這一次看主要是把各種資料結構做到心中有數,概念清晰,瞭解各自有哪些經典的演算法和演算法思路原理。以後若要用到特定的結構和演算法再去演算法導論中詳細研讀。下面是今天的學習筆記。
排序(ranking)
1.排序可看成是對線性表的操作;多個關鍵字排序可轉化成單個關鍵字排序;排序的穩定和不穩定;主要講內排序,其排序演算法主要受3方面影響:時間效能,輔助空間,演算法複雜性。
2.按複雜度分:簡單演算法(冒泡排序、簡單選擇排序、直接插入排序),改進演算法(希爾排序、堆排序、歸併排序、快速排序)
3.冒泡排序
基本思想:是一種交換排序,兩兩比較相同相鄰記錄的關鍵字,如果反序則交換,直到沒有反序的記錄為止。
初級版:找第i小的記錄時,將第i個格子裡的元素與i+1位比較,小的放i位;繼續將i位與i+2位比較,直至將i位於第n位比較交換,得到第i小的記錄;再進行下一輪找第i+1小的記錄。
正宗的冒泡排序:找第i小的記錄時,要同時比較和交換 n-i 次(總n個記錄),小的元素經比較交換上浮至第i個位置中。
冒泡最佳化:若在某輪上浮中沒有發生交換(設定一個是否發生交換的標記flag),則已有序,停止之後的冒泡,結束程式。
4.簡單選擇排序
原理:通過n-i次比較,從n-i-1個記錄中選出最小後,將其與第i位的記錄交換;
與冒泡的區別:冒泡是比較一次伴隨一次交換;簡單選擇法是一輪中多次比較完後,進行一次交換。
5.直接插入排序
原理:將一個記錄插入到已經排好序的有序表中,從而得到一個新的、記錄數增1的有序表。類似於理撲克的過程。
6.希爾排序
基本有序:小的基本在前,大的基本在後。
原理:跳躍分割——不穩定,將相聚某個增量的記錄組成一個子序列,在子序列內部進行直接插入都的結果依然是基本有序的。將間隔由n/2依次按規律減小,直至1(最後一個增量必須是1)
7.堆排序
堆:是這樣性質的完全二叉樹——每個結點的值都大於或等於其左右孩子結點的值——大頂堆(或<=小頂堆)。
排序背景:簡單選擇排序在每輪比較時,並沒有把比較結果儲存下來,導致後幾輪重複前面的一些比較——改進就是每輪選到最小記錄時,根據該輪的比較結果對其他記錄做出相應的調整。
排序原理:將待排序的序列構造成一個大頂堆(HeapAdjust函數),此時整個序列的最大值就是根節點,將其移除後由樹的末尾元素填補得到一個新的完全二叉樹,將其用HeapAdjust函數重新調整為一個大頂堆,重複上述過程,直至最後一個有孩子的結點。
大頂堆建構函式HeapAdjust:將當前結點找到他左右子結點的較大值,互換,再找到其子節點的較大值互換。
8.歸併排序
原理:假設初序列含n個記錄,看做n個長為1的有序的子序列,兩兩有序歸併(merge函數),得到不小於n/2個的最小整數有序序列,再兩兩歸併,直至得到一個長為n的有序序列為止;遞迴;
merge函數:合并兩個有序序列SR[i..m]、SR[m+1..n];i,j對應的記錄誰小誰存入TR[k],誰就++,另一不變,同時k++;進入下一輪,i,j對應的元素繼續比較..,直至i增加到大於m或j增加到大於n。
改進佔用記憶體的遞迴實現歸併排序:用迭代。
9.快速排序
原理:通過一趟排序對待排序的序列分成兩部分,左邊的記錄均比樞軸小,右邊的比樞軸大——Partiton函數實現;再將左右兩部分內部分別進行上述分割,遞迴實現。
Partiton函數(返回左右排好後樞軸pivot所在的位置):每一輪中,找到序列右端起j--第一個比pivot小的與其交換,使小的在其左側,找到序列左端起i++第一個比pivot大的與其交換,使大的在其右側;直至i和j相等為止。
最佳化——Partiton函數演算法實現中對於樞軸pivot的選擇,固定選取、隨機選取、三數取中、九數取中;
最佳化不必要的交換:Partiton函數中的每輪左右排序,比較多次,但只交換一次。
最佳化小數組時的排序方案:當high-low小於某個常數時,直接用直接排序法。
最佳化遞迴轉迭代省空間。
10.上述7種排序的時間效能(最好、最差、平均),空間效能、穩定性、適用的序列數量規模等的綜合考量選擇最合適的排序方法。