1. 程式人生 > >資料結構的各種排序演算法穩定性比較

資料結構的各種排序演算法穩定性比較

一、前面有講到了9種排序演算法:

1.簡單選擇排序

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.在涉及到不同位置元素交換的演算法中除了冒泡和直接插入排序是穩定的,其他都是不穩定的.

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

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

相關推薦

資料結構各種排序演算法穩定性比較

一、前面有講到了9種排序演算法: 1.簡單選擇排序 2.堆排序 (1和2是屬於選擇排序) 3.直接插入排序 4.希爾排序 (3和4屬於插入排序,有時把改進後的直接插入排序叫做二分插入) 5.氣泡排序 6.快速

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

排序演算法穩定性 所謂穩定性是指待排序的序列中有兩元素相等,排序之後它們的先後順序不變.假如為A1,A2.它們的索引分別為1,2.則排序之後A1,A2的索引仍然是1和2. 穩定也可以理解為一切皆在掌握中,元素的位置處在你在控制中.而不穩定演算法有時就有點碰運氣,隨機的成分.

(最全)資料結構排序演算法時間複雜度,空間複雜度,穩定性比較

演算法 時間複雜度 最好 ---------- 平均 --------- 最壞 直接插入排序 o(n)-------- o(n的平方) ---------

資料結構排序演算法和查詢演算法的時間複雜度和空間複雜度)

這是從大神給多的網站上找到的演算法的時間複雜度趨勢和各個常用結構的複雜度截圖。     演算法的時間複雜度,用來度量演算法的執行時間,記作: T(n) = O(f(n))。它表示隨著 輸入大小n 的增大,演算法執行需要的時間的增長速度可以用 f(n) 來描

資料結構排序演算法(五)

// 索引堆 function swap(arr, x, y) {             var temp = arr[x];         

【Java】 大話資料結構(17) 排序演算法(4) (歸併排序資料結構演算法合集 資料結構演算法合集

本文根據《大話資料結構》一書,實現了Java版的堆排序。 更多:資料結構與演算法合集 基本概念   歸併排序:將n個記錄的序列看出n個有序的子序列,每個子序列長度為1,然後不斷兩兩排序歸併,直到得到長度為n的有序序列為止。   歸併方法:每次在兩個子序列中找到較小的那一個賦值給合併序列(通過指標進行操

【Java】 大話資料結構(18) 排序演算法(5) (直接插入排序資料結構演算法合集 資料結構演算法合集

本文根據《大話資料結構》一書,實現了Java版的直接插入排序。 更多:資料結構與演算法合集 基本概念   直接插入排序思路:類似撲克牌的排序過程,從左到右依次遍歷,如果遇到一個數小於前一個數,則將該數插入到左邊所有比自己大的數之前,也就是說,將該數前面的所有更大的數字都後移一位,空出來的位置放入該數。

資料結構排序演算法

JavaScript實現排序演算法 程式碼實現 const ArrayList = function() { let array = [], length = 0; this.insert = function(item) {

資料結構-八大排序演算法

目錄 排序分類一覽 型別一 交換排序 氣泡排序 快速排序 型別二 插入排序 直接插入排序 希爾排序 型別三 選擇排序 簡單選擇排序

資料結構 基礎排序演算法

排序 研究 排序 排序 研究 順序表 內部排序與外部排序 排序策略 交換排序 氣泡排序 效率分析: 快速排序: 效率分析

各種排序演算法效能比較

原帖 http://www.cnblogs.com/wangjiahong/p/3570465.html?utm_source=tuicool 下面是我直接做成的原始碼,直接可以執行。 大家可以根據需要測試 using System; using System.Col

王道資料結構內部排序演算法總結

首先看一下內部排序分類以及各個演算法的時間複雜度和空間複雜度   一、插入排序      1、直接插入排序(Straight Insertion Sort)的基本思想是:把n個待排序的元素看成為一個有序表和一個無序表。開始時有序表中只包含1個元素,無序表中包含有n-1個元素,排序過程

資料結構排序演算法(五)-直接插入排序,希爾排序,直接選擇排序

直接插入排序:時間複雜度:O(n^2) 基本演算法思路是:把後面待排序的記錄按其關鍵字的大小逐個插入到一個已經排好序的有序序列中,直到所有記錄插完為止,得到一個新的有序序列。(無序插入前面有序) 演算

資料結構--七大排序演算法總結

面試中,無論是問還是寫,排序被問到的次數總是很多。總結一些八大排序演算法。 排序演算法 七大排序時間複雜度&空間複雜度&穩定性 初始序列對演算法效能有無影響 排序方法 初始序列有無影響 最好情況

資料結構排序演算法- 二叉樹排序(7)

1,二叉樹排序演算法 基本思想:二叉排序樹:要麼是空樹,要麼滿足以下條件:若左子樹不空,則左子樹所有結點的值均小於根結點的值,若右子樹不空,右子樹所有結點的值均大於根結點的值;左子樹和右子樹也是一顆二叉排序樹。對於二叉排序樹進行中序遍歷,得到就是一個有序的序列。因此二叉樹排

常用資料結構排序演算法實現、適用場景及優缺點(Java)

1.下壓棧(後進先出)(能夠動態調整陣列大小的實現): package Chapter1_3Text; import java.util.Iterator; public class ResizingArrayStack<Item> implements

Java資料結構排序演算法(氣泡排序,選擇排序,插入排序,希爾排序,快速排序,堆排序和合並排序

public class 氣泡排序 { public static void main(String[] args) { int a[] = { 1, 9, 6, 8, 5, 65, 65, 84, 1, 2, 5, 23, 7, 889 }; for (int i

演算法資料結構排序演算法的相關知識,簡單易懂。

一、    氣泡排序 1)  概要 本章介紹排序演算法中的氣泡排序,重點講解氣泡排序的思想。 目錄 1. 氣泡排序介紹 2. 氣泡排序圖文說明 3. 氣泡排序的時間複雜度和穩定性 4. 氣泡排序實現 4.1 氣泡排序C實現 4.2 氣泡排序C++實現 4.

[C++]資料結構排序演算法Part1----氣泡排序、選擇排序、插入排序、堆排序

1.氣泡排序:正所謂人如其名,氣泡排序正是使用了“冒泡”的方法對元素進行了排序。 它的演算法思想就是在每次遍歷的時候從頭到尾比較相鄰的兩個元素大小,將較小的元素“冒”到前面來,把最大的元素移向隊尾,使得元素變得有序。 我們把已經排好序的區域稱為有序區,相對應的便是沒排好順序

各種排序演算法比較(1):穩定性

前面有講到了9種排序演算法:      (3和4屬於插入排序,有時把改進後的直接插入排序叫做二分插入) 5.氣泡排序         6.快速排序     (5和6屬於交換排序.交換排序顧名思義是不停的交換資料位置.但實際上選擇排序也在不停的交換元素,但次數較少,只有