1. 程式人生 > >數據結構中各種排列三平臺搭建序算法的穩定性比較

數據結構中各種排列三平臺搭建序算法的穩定性比較

重點 分配排序 相等 8 8 重復元素 屬於 遍歷 使用 可能

1.簡排列三平臺搭建論壇:haozbbs.com Q1446595067單選擇排序 2.堆排序 (1和2是屬於選擇排序)

3.直接插入排序 4.希爾排序 (3和4屬於插入排序,有時把改進後的直接插入排序叫做二分插入)

5.冒泡排序 6.快速排序 (5和6屬於交換排序.交換排序顧名思義是不停的交換數據位置.但實際上選擇排序也在不停的交換元素,但次數較少,只有找到最大值才一次交換.側重點還是在通過遍歷或堆來選擇出最值.而冒泡排序就是通過不停交換相鄰元素得出最大值,快速排序也在不停交換元素使序列一步步接近有序.側重在交換)

7.基數排序 8.桶排序 (7和8屬於分配排序)

9.歸並排序

面對這以多排序算法你可能郁悶著要自己排序時用哪種算法好呢? 每種算法適用哪些場景?

為了對比上面各種不同算法,可以從如下幾個方面來考慮.

1.排序算法的穩定性

2.排序算法時間復雜度

3.排序算法空間復雜度

4.各種算法適用的最佳場景.

排序算法穩定性
所謂穩定性是指待排序的序列中有兩元素相等,排序之後它們的先後順序不變.假如為A1,A2.它們的索引分別為1,2.則排序之後A1,A2的索引仍然是1和2.

穩定也可以理解為一切皆在掌握中,元素的位置處在你在控制中.而不穩定算法有時就有點碰運氣,隨機的成分.當兩元素相等時它們的位置在排序後可能仍然相同.但也可能不同.是未可知的.

另外要註意的是:算法思想的本身是獨立於編程語言的,所以你寫代碼去實現算法的時候很多細節可以做不同的處理.采用不穩定算法不管你具體實現時怎麽寫代碼,最終相同元素位置總是不確定的(可能位置沒變也可能變了).而穩定排序算法是你在具體實現時如果細節方面處理的好就會是穩定的,但有些細節沒處理得到的結果仍然是不穩定的.

比如冒泡排序,直接插入排序,歸並排序雖然是穩定排序算法,但如果你實現時細節沒處理好得出的結果也是不穩定的.

穩定性的用處

我們平時自己在使用排序算法時用的測試數據就是簡單的一些數值本身.沒有任何關聯信息.這在實際應用中一般沒太多用處.實際應該中肯定是排序的數值關聯到了其他信息,比如數據庫中一個表的主鍵排序,主鍵是有關聯到其他信息.另外比如對英語字母排序,英語字母的數值關聯到了字母這個有意義的信息.

可能大部分時候我們不用考慮算法的穩定性.兩個元素相等位置是前是後不重要.但有些時候穩定性確實有用處.它體現了程序的健壯性.比如你網站上針對最熱門的文章或啥音樂電影之類的進行排名.由於這裏排名不會像我們成績排名會有並列第幾名之說.所以出現了元素相等時也會有先後之分.如果添加進新的元素之後又要重新排名了.之前並列名次的最好是依然保持先後順序才比較好.

哪些算法是穩定的呢
穩定性算法: 基數排序 , 直接插入排序 , 冒泡排序, 歸並排序

不穩定性算法: 桶排序, 二分插入排序,希爾排序, 快速排序, 簡單選擇排序,堆排序

各種算法穩定性詳解
(1)基數排序(穩定)與桶排序(不穩定)

這兩種算法都是屬於分配排序算法.(利用元素值本身的信息直接映射到一個輔助序列中變成有序的.而不是通過與其他元素比較確定順序位置)

基數排序因為在是把低位按順序映射到一個臨時序列中去,是依次序映射,沒有涉及到數據位置的變動.然後再按高位順序映射.所以相同元素也是按次序映射過去.所以是穩定的

如果數據元素沒有重復的則采用簡單桶排序,此時沒有重復元素,所以自然不存在穩不穩定這一說.如果有重復元素得用改進的桶排序.此時輔助的臨時數組只是通過索引來識別待排序元素的鍵值.丟失了其他信息(這是所有采用輔助的臨時序列的算法中唯一一個會丟失信息的算法).假如待排序元素是一個map類型,按它的鍵值來排序.其他算法采用輔助序列時是把map類型做為元素去考慮的.而只有改進的桶排序不會把map類型當元素,只是利用到了鍵值信息. 這樣一來就無法區分鍵值相同的信息,因此自然是不穩定的算法了啊.

(2)歸並排序(穩定)

歸並排序使得了遞歸的思想,把序列遞歸的分割成小序列,然後合並排好序的子序列.當有序列的左右兩子序列合並的時候一般是先遍歷左序列,所在左右序列如果有相等元素,則處在左邊的仍然在前,這就穩定了.但是如果你非得先遍歷右邊序列則算法變成不穩定的了.雖然這樣排出來的序也是對的,但變成了不穩定的,所以是不太好的實現.

(3)簡單選擇排序(不穩定)與堆排序(不穩定)

這兩種算法都屬於選擇排序.(從待排序的元素中挑選出最大或最小值.下面的例子以最小值為例)

簡單選擇排序由於選出最小值後需要交換位置,位置一變就會變得不穩定.例如8 3 8 1.當從左往右遍歷找最小值時,找到了1,這就需要把8跟1交換.這樣兩個相等元素8的位置就變了.

堆排序的話,也會存在跟上面一樣的交換最大值的位置會導致不穩定.例如有大堆 8 8 6 5 2.先選出第一個最大值8,放最末尾.此時就不穩定了.因為第二個8就跑它前面去了.

(4)冒泡排序(穩定)與快速排序(不穩定)

這兩種算法都屬於交換排序.

冒泡是通過不停的遍歷,以升序為例,如果相鄰元素中左邊的大於右邊的則交換.碰到相等的時就不交換保持原位.所以是穩定的.當然如果你非得吃飽了撐著了,在碰到相等的時也交換下,那肯定變成不穩定的算法了.

快速排序是不穩定的.舉例8 5 6 6 .以8為基準,第一趟交換後最後一個6跑到第一位,8到最後.第二趟交換.這個6跑到5的位置.變成有序的了.兩個6位置變了,所以是不穩定的.

(5)直接插入(穩定),二分插入排序(不穩定)與希爾排序(不穩定)

直接插入時是先在已排序好的的子序列中找到合適的位置再插入.假設左邊是已排序的,右邊是沒排序的.通過從後向前遍歷已排序序列,然後插入,此時相等元素依然可以保持原有位置.但是如果你從前向後遍歷已排序序列就會是不穩定排序了.

二分插入排序是不穩定的,因為通過二分查找時得到的位置不穩定.例如3 4 4 5 4.但把最後一個4插入時肯定會跑到第二個4前面去了.所以是不穩定的.

通過上面的分析我們可以得出這樣一個經驗之談.
1.只要不涉及到兩個元素之間位置的交換就肯定是穩定的排序算法.比如歸並排序,基數排序.(桶排序不穩定是個特例,因為它丟失了附帶信息,不然的話可以弄成穩定排序的)

2.在涉及到不同位置元素交換的算法中除了冒泡和直接插入排序是穩定的,其他都是不穩定的.

你可以這樣想,之所以出現相同元素位置變了就是其中一個交換位置時從另一個頭頂跳過去了,而冒泡算法是相鄰位置互換,跳不過去的,碰到相等元素的時候就停住不交換了.

而直接插入排序是往已排好序的序列中插入.所以你通過由後往前遍歷碰到相等的時就停住,這樣也能保持穩定.但記住一定得從後往前遍歷,不然也會不穩定.(所以說直接插入是半穩吧,而冒泡是非常的穩啊,除非你閑得蛋痛非得把兩相等的元素兩兩交換)

數據結構中各種排列三平臺搭建序算法的穩定性比較