排序的穩定性
2019-11-10 09:42:11 by沖沖
1、穩定性
① 定義:能保證兩個相等的數,經過排序之后,其在序列的前后位置順序不變。(A1=A2,排序前A1在A2前面,排序后A1還在A2前面)
② 意義:穩定性本質是維持具有相同屬性的數據的插入順序,如果后面需要使用該插入順序排序,則穩定性排序可以避免這次排序。
比如,公司想根據“能力”和“資歷”(以進入公司先后順序為標准)作為本次提拔的參考,假設A和B能力相當,如果是穩定性排序,則第一次根據“能力”排序之后,就不需要第二次根據“”資歷
排序了,因為“資歷”排序就是員工插入員工表的順序。如果是不穩定排序,則需要第二次排序,會增加系統開銷。
2、分類
① 穩定性排序:冒泡排序,插入排序、歸並排序、基數排序
② 不穩定性排序:選擇排序、快速排序、希爾排序、堆排序
3、例析
(1)穩定性排序
① 冒泡排序
冒泡排序本質是,從左到右開始不斷把大的元素往后調(或者,從右往左開始不斷把小的元素往前調)。比較是比較相鄰的兩個元素,交換也是發生在這兩個元素之間。所以,如果兩個元素相等,你總不會無聊地把它倆交換一下吧。如果兩個相等元素沒有相鄰,那么也會經過一波兩兩交換使他們相鄰,此時也不會發生交換。
② 插入排序
插入排序本質是,在一個已經有序的小序列基礎上,通過從右往左比較,一次插入一個元素。剛開始這個小序列只有一個元素。比較是從有序序列的末尾開始,想插入的元素和已經有序的最大者開始比較,如果比它大則直接插在其后面,否則一直往前比較,直到找到比它小的或與它相等的,然后插在其后面。
③ 歸並排序
歸並排序本質是,把序列遞歸地分成短序列,遞歸出口是短序列只有1個元素(此時認為直接有序)或者2個序列(1次比較和交換),然后把各個有序的短序列合並成一個有序的長序列,不斷合並直到原序列全部排好序。當存在1個或2個元素時,1個元素不會交換,2個元素如果大小相等也沒有人故意交換,因此不會破壞穩定性。那么在短的有序序列合並的過程中,穩定是否受到破壞?沒有。合並過程中當兩個當前元素相等時,處在前面序列的元素依然保存在結果序列的前面。
④ 基數排序
基數排序本質是,按照低位先排序,然后收集,再按照高位排序,然后再收集,依次類推,直到最高位。比如序列“171(1),331,171(2)”,低位排序(個位)結果是“171(1),331,171(2)”,高位排序(十位)結果是“331171(1),171(2)”,高位排序(百位)結果是“171(1),171(2),331”。
(2)不穩定性排序
① 選擇排序
選擇排序本質是,給每個位置選擇剩下元素中最小的。比如給第一個位置選擇最小的,給第二個位置選擇剩余元素里面第二小的,依次類推。例如序列“5(1),8,5(2),2,9”,5(1)會和2交換,破壞穩定性。
② 快速排序
快速排序本質是,選取第一個元素為中樞元素a[center_index](index=0)。從兩個方向入手,首先左邊的i下標一直往右走,當a[i] > a[center_index]停止,由右邊的j下標開始往左走,當a[j] <= a[center_index]停止,由左邊i下標開始剛才的表演,重復上面的過程,直到i>j,交換a[j]和a[center_index],完成一趟快速排序。在中樞元素和a[j]交換的時候,很有可能把前面的元素的穩定性打亂,比如序列為 “5,3(1),4,3(2),8,11,9”, 現在中樞元素5和3(2)交換就會把元素3的穩定性打亂。不穩定發生在中樞元素和a[j]交換的時刻。
③ 希爾排序
希爾排序本質是,按照不同步長對元素進行插入排序,當剛開始元素很無序的時候,步長最大,所以插入排序的元素個數很少,速度很快;當元素基本有序了,步長很小,插入排序對於有序的序列效率很高。所以,希爾排序的時間復雜度會比o(n^2)好一些。由於多次插入排序,我們知道一次插入排序是穩定的,不會改變相同元素的相對順序,但在不同的插入排序過程中,相同的元素可能在各自的插入排序中移動,最后其穩定性就會被打亂,所以shell排序是不穩定的。
④ 堆排序
堆排序本質是,我們知道堆的結構是節點i的孩子為2*i和2*i+1節點,大頂堆要求父節點大於等於其2個子節點,小頂堆要求父節點小於等於其2個子節點。在一個長為n的序列,堆排序的過程是從第n/2開始和其子節點共3個值選擇最大(大頂堆)或者最小(小頂堆),這3個元素之間的選擇當然不會破壞穩定性。但當為n/2-1, n/2-2, ...1這些個父節點選擇元素時,就會破壞穩定性。有可能第n/2個父節點交換把后面一個元素交換過去了,而第n/2-1個父節點把后面一個相同的元素沒有交換,那么這2個相同的元素之間的穩定性就被破壞了。所以,堆排序不是穩定的排序算法。
4、時間復雜度和空間復雜度
類別 | 排序方法 | 時間復雜度 | 空間復雜度 | 穩定性 | 應用依據 | 剖析 | ||
平均情況 | 最好情況 | 最壞情況 | 輔助內存 | |||||
插入排序 | 直接插入 | O(n2) | O(n) | O(n2) | O(1) | 穩定 | 大部分已經排序 | https://www.cnblogs.com/yadiel-cc/p/11829389.html |
希爾排序 | O(n1.3) | O(n) | O(n2) | O(1) | 不穩定 | https://www.cnblogs.com/yadiel-cc/p/11829405.html | ||
選擇排序 | 直接選擇 | O(n2) | O(n2) | O(n2) | O(1) | 不穩定 | n比較小 | https://www.cnblogs.com/yadiel-cc/p/11829400.html |
堆排序 | O(nlog2n) | O(nlog2n) | O(nlog2n) | O(1) | 不穩定 | n比較大 | https://www.cnblogs.com/yadiel-cc/p/11829407.html | |
交換排序 | 冒泡排序 | O(n2) | O(n) | O(n2) | O(1) | 穩定 | n比較小 | https://www.cnblogs.com/yadiel-cc/p/11829384.html |
快速排序 | O(nlog2n) | O(nlog2n) | O(n2) | O(log2n)~O(n) | 不穩定 | n比較大 | https://www.cnblogs.com/yadiel-cc/p/11829403.html | |
歸並排序 | O(nlog2n) | O(nlog2n) | O(nlog2n) | O(1) | 穩定 | n比較大 | https://www.cnblogs.com/yadiel-cc/p/11829394.html | |
基數排序 | O(1) | 穩定 | https://www.cnblogs.com/yadiel-cc/p/11829398.html |