O n 的三個排序演算法

2021-10-12 01:58:08 字數 3634 閱讀 9423

今天覆習下最簡單的三個排序演算法,乙個是選擇排序,乙個是插入排序,乙個是氣泡排序,三者時間複雜度都是o(n²),通過分析來發現三者的優劣,以及對最好的情況和最壞的情況進行分析。 另外,這三中排序演算法都是基於比較的排序演算法。基於比較的排序演算法的執行過程,會涉及兩種操作,一種是元素比較大小,另一種是元素交換或移動。所以,如果我們在分析排序演算法的執行效率的時候,應該把比較次數和交換(或移動)次數也考慮進去。

選擇排序是一種簡單直觀的排序演算法,工作原理為:在未排序的序列中找出最小(大)元素與第乙個位置的元素交換位置,原理如下圖所示:

選擇排序的靜態圖:

選擇排序是一種不穩定的排序演算法。 從圖中可以看出來,選擇排序每次都要找剩餘未排序元素中的最小值,並和前面的元素交換位置,這樣破壞了穩定性。

選擇排序的最好情況時間複雜度、最壞情況和平均情況時間複雜度都為o(n²)

首先,我們將陣列中的資料分為兩個區間,已排序區間和未排序區間。初始已排序區間只有乙個元素,就是陣列的第乙個元素。插入演算法的核心思想是取未排序區間中的元素,在已排序區間中找到合適的插入位置將其插入,並保證已排序區間資料一直有序。重複這個過程,直到未排序區間中元素為空,演算法結束。

靜態圖展示

}換個比較簡潔的寫法:

//更簡潔的寫法:替換上面的break

public

void

execsort

(int arr)}}

插入排序的改進

插入排序和選擇排序的對比

其實我們很容易發現選擇排序的最致命的缺點就是兩層for迴圈需要完全走完才能完成排序,而插入排序則不需要。所以選擇排序在任何情況下都是比較慢的。插入排序則不同,最壞的情況下(其實就是逆序了)才是o(n²),如果是已經有序,或者大部分有序,還是非常快的,比如在我自己的電腦上排一億個有序的數,才0.035s,這種速度比n*log(n)的排序演算法效能還高,至於選擇排序的話我等了1分鐘還沒排出來,直接stop了。

所以o(n²)級別的排序演算法並非一無是處!下面我們看看氣泡排序吧!

在插入排序中,對於值相同的元素,我們可以選擇將後面出現的元素,插入到前面出現元素的後面,這樣就可以保持原有的前後順序不變,所以插入排序是穩定的排序演算法。

上面已經說過了,如果要排序的資料已經是有序的,我們並不需要搬移任何資料。如果我們從尾到頭在有序資料組裡面查詢插入位置,每次只需要比較乙個資料就能確定插入的位置。所以這種情況下,最好是時間複雜度為 o(n)

如果陣列是倒序的,每次插入都相當於在陣列的第乙個位置插入新的資料,所以需要移動大量的資料,所以最壞情況時間複雜度為 o(n²)。

氣泡排序也屬於一種典型的交換排序,交換排序顧名思義就是通過元素的兩兩比較,判斷是否符合要求,如過不符合就交換位置來達到排序的目的。氣泡排序名字的由來就是因為在交換過程中,類似水冒泡,小(大)的元素經過不斷的交換由水底慢慢的浮到水的頂端。

如果用靜態圖來展示的話就是這個樣子:

}優化版本定義乙個標誌位用來表示當前第i趟是否有交換,如果有,則要進行i+1趟,如果沒有則說明當前陣列已經完成排序,不需要剩下的比較:

public

static

void

bubblesortoptimize

(int arr)

}if(flag) return;}}

其實氣泡排序還有更優化的做法,那就是記錄最後一次交換的位置:

public

static

void

bubblesortoptimizeplus

(int arr)

}if(flag) return;

k = pos;}}

排序隨機數組的時候,優化效果一般,但是排序幾乎有序的陣列和本來就有序的陣列還是有優化效果的:

第二種優化之後才0.049秒,不優化是22秒。

氣泡排序是穩定排序,在氣泡排序中,只有交換才可以改變兩個元素的前後順序。為了保證氣泡排序演算法的穩定性,當有相鄰的兩個元素大小相等的時候,我們不做交換,相同大小的資料在排序前後不會改變順序,所以氣泡排序是穩定的排序演算法

最好情況下,要排序的資料已經是有序的了,我們只需要進行一次冒泡操作,就可以結束了,所以最好情況時間複雜度是 o(n)。而最壞的情況是,要排序的資料剛好是倒序排列的,我們需要進行 n 次冒泡操作,所以最壞情況時間複雜度為 o(n²)。

一看圖就明白了什麼排序演算法最實用了吧,那就是插入排序。 這三種時間複雜度為 o(n²) 的排序演算法中,氣泡排序、選擇排序,可能就純粹停留在理論的層面了,學習的目的也只是為了開拓思維,實際開發中應用並不多,但是插入排序還是挺有用的。

賞 謝謝你請我喝咖啡

支付寶

三個簡單的排序

氣泡排序 從第乙個元素開始,和它右邊的哪個元素比較,如果它比右邊的哪個元素大的話,就交換位置,經過第一次後,最右邊的那個元素,就是最大的哪個元素.第二次同樣,從第一元素開始,但是比較到倒數第二個元素,這樣右邊第二個元素就是第二高的元素.依次這樣下去,每次比較的結束值就是,比上一次小乙個,直到結束的標...

scala的三個排序方法

def sorted b a implicit ord ordering b reprscala val a list 10,5,8,1,7 sorted a list int list 1,5,7,8,10 scala val b list banana pear orange sorted b ...

三個字元排序

時間限制 3000 ms 記憶體限制 65535 kb 難度 2 描述 輸入三個字元 可以重複 後,按各字元的ascii碼從小到大的順序輸出這三個字元。輸入第一行輸入乙個數n,表示有n組測試資料。後面的n行輸入多組資料,每組輸入資料都是佔一行,有三個字元組成,之間無空格。輸出對於每組輸入資料,輸出一...