1. 程式人生 > >各種排序演算法穩定性比較

各種排序演算法穩定性比較

排序演算法穩定性

所謂穩定性是指待排序的序列中有兩元素相等,排序之後它們的先後順序不變.假如為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.在涉及到不同位置元素交換的演算法中除了冒泡和直接插入排序是穩定的,其他都是不穩定的.

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

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