選擇排序
排序系列開篇問題
內容小結
本節我們一期學習乙個新的排序演算法,插入排序
首先需要思考,乙個有序的陣列,在往裡面插入乙個新的資料之後,如何保持資料有序呢?很簡單,我們只需要遍歷資料,找到資料應該插入的地方,將其插入即可。
這是乙個動態排序的過程,即動態的往有序集合裡新增資料,我們可以通過這種方式,保持集合中的資料一直有序。而對於一組靜態資料,我們也可以借鑑上面的插入方法,來進行排序,於是就有了插入排序。
受限,我們將陣列中的資料分為兩個區域,已排序區域和未排序區域。初始已排序區間只有乙個元素,就是陣列的第乙個元素。插入演算法的核心思想就是取未排序區間的元素,在已排序區間中找到合適的位置將其插入,並保證已排序區間的資料,一直有序。重複這個過程,直到未排序區間為空,演算法結束。
如下圖所示,要排序的資料是4、5、6、1、3、2,其中左側為已排序區間,右側是未排序區間。
插敘排序也包含兩種操作,一種是元素的比較,一種是元素的移動。當我們需要講乙個資料 a 插入到已排序區間時,需要拿 a 與已排序區間的元素依次比較大小,找到合適的插入位置。
找到插入點後,我們還需要把插入點之後的元素順序往後移動一位,這樣才能騰出位置給 a 元素插入。
對於不同的查詢插入點的方法(從頭到尾,從尾到頭),元素的比較次數是有區別的,但對於乙個給定的初始序列,移動操作次數總是固定的。就等於逆序度。
為什麼說義移動次數就等於逆序度呢?把上面的例子做乙個分析就一目了然了
滿有序度是n*(n - 1)/2 = 15
function
insertsort
(arr)
else
}//插入資料
arr[j+1]
= value;
}}
從實現過程可以看出,插入排序演算法的執行並不需要額外的儲存空間,所以空間複雜度是 o(1),也就是說,這是乙個原地排序演算法。
在插入排序中,對於值相等的元素,我們可以選擇將後面出現的,插入到前面出現元素的後面,這樣就可以保證原有的前後順序不變,所以插入排序是穩定的排序演算法。
如果要排序的資料已經是有序的,我們並不需要搬移任何資料。如果我們從尾到頭在有序資料組裡面查詢插入位置。每次只需要比較乙個資料就能確定插入位置。所以這種情況下,最好的時間複雜度為o(n)。
如果陣列是倒序的,每次插入都相當於在陣列的第乙個位置插入資料,需要移動大量的資料,所以最壞情況的時間複雜度為o(n2)。
還記得最開始我們討論的,在陣列中插入乙個資料的平均時間複雜度是多少嗎?沒錯就是o(n),所以對於插入排序來說,每次插入都相當於在陣列中插入乙個資料,迴圈執行 n 次插入操作,所以平均時間複雜度為o(n2)。
選擇排序的實現方式有點類似於插入排序,也分已排序區間和未排序區間。但是選擇排序每次會從未排序區間中找到最小的元素,將其放到已排序區間的末尾。
照例,思考三個問題,前面的解釋已經很詳細了,這裡就直接公布答案。
選擇排序的控制項複雜度為o(1),是一種原地排序演算法。選擇排序的最好情況、最壞情況和平時情況時間複雜度都為o(n2)。有興趣的同學可以自己分析一下。
選擇排序是穩定的排序演算法嗎?這個問題需要重點討論。
答案是否定的,選擇排序是一種不穩定的排序演算法。從前面那張圖可以看出,選擇排序每次都要找出剩餘未排序元素中的最小值,然後和前面的元素交換位置,這樣就破壞了穩定性。
比如5、8、5、2、9 這組資料,使用選擇排序的話,第一次選擇 2 ,與第乙個 5 交換位置,那麼這兩個 5 的前後順序就變了,所以不穩定。正因如此,相對於氣泡排序和插入排序,選擇排序就稍稍遜色一些。
我們已經學習了三種排序,其中氣泡排序和插入排序的時間複雜度都是 o(n2)。都是原地排序演算法,為什麼插入排序比氣泡排序更受歡迎?
因為之前我們說過,氣泡排序不管怎麼優化,其元素交換的次數是乙個固定值,是原始資料的逆序度。插入排序也是一樣的,不管怎麼優化,元素移動的次數也是逆序度。
但是,從**實現上來看,氣泡排序的資料交換,要比插入排序的資料移動複雜的多,冒泡需要三個賦值,而插入只需要乙個,下面是**部分:
if
(arr[j]
> arr[j +1]
)
if
(arr[j]
> value)
else
我們把執行乙個賦值語句的時間記做單位時間unit
,然後分別用氣泡排序和插入排序對同乙個逆序度是 k 的陣列進行排序。用氣泡排序,需要 k 次交換,每次需要三個賦值語句,所以交換操作總耗時就是3*k unit
而插入排序排序中移動操作只需要 k 個單位時間。
這個只是理論的推測,大家可以分別用兩個方法對乙個陣列進行排序,計算一下演算法執行時間,我以前做過乙個隨機生成1000個陣列,每個陣列包含200個資料的實驗,氣泡排序大概需要 700ms , 而插入排序只需要 100ms 就能搞定。
當然插入排序也是可以進一步優化的,具體方法可以學習一下希爾排序。
想要分析,評價乙個排序演算法,需要從執行效率,記憶體消耗,穩定性三個方面考慮。因此這一節中,我們分析了三種,時間複雜度為 o(n2) 的排序演算法
上面三種演算法中,氣泡排序,選擇排序,基本都是停留在理論層面,了解一下,拓展一下思路,實際開發中運用的並不多,但是插入排序還是很有用的,後面講排序優化的時候,會講到有些程式語言中的排序函式,就是使用的插入排序演算法。
文中不足之處,請各位大佬指點。
排序演算法 二 冒泡 選擇 插入排序
1.1 基本介紹 氣泡排序 bubble sorting 的基本思想是 通過對待排序序列從前向後 從下標較小的元素開始 依次比較相鄰元素的值,若發現逆序則交換,使值較大的元素逐漸從前移向後部,就象水底下的氣泡一樣逐漸向上冒。優化 因為排序的過程中,各元素不斷接近自己的位置,如果一趟比較下來沒有進行過...
《演算法》選擇排序 插入排序 氣泡排序
選擇排序,演算法 p156 package algorithm public class selection p156 for int i 0 i n i public static void main string args test.sort a 思路 將第乙個元素與剩餘所有元素相比,如果有比第...
排序演算法 插入排序和選擇排序
二者演算法分析 穩定性 時間複雜度 希爾排序 希爾排序是直接插入排序的優化,但當待排序數列很大時,預排序過程效率會降低許多,時間複雜度為o n2n2 空間複雜度 空間複雜度都為o 1 在進行排序時,會建立臨時常數個臨時變數用於控制下標 直接插入排序 void insertsort datatype ...