排序與搜索
排序算法(英語:Sorting algorithm)是一種能將一串數據依照特定順序進行排列的一種算法。
排序算法的穩定性
穩定性:穩定排序算法會讓原本有相等鍵值的紀錄維持相對次序。也就是如果一個排序算法是穩定的,當有兩個相等鍵值的紀錄R和S,且在原本的列表中R出現在S之前,在排序過的列表中R也將會是在S之前。
當相等的元素是無法分辨的,比如像是整數,穩定性并不是一個問題。然而,假設以下的數對將要以他們的第一個數字來排序。
(4, 1) (3, 1) (3, 7)(5, 6)
在這個狀況下,有可能產生兩種不同的結果,一個是讓相等鍵值的紀錄維持相對的次序,而另外一個則沒有:
(3, 1) (3, 7) (4, 1) (5, 6) (維持次序)
(3, 7) (3, 1) (4, 1) (5, 6) (次序被改變)
不穩定排序算法可能會在相等的鍵值中改變紀錄的相對次序,但是穩定排序算法從來不會如此。不穩定排序算法可以被特別地實現為穩定。作這件事情的一個方式是人工擴充鍵值的比較,如此在其他方面相同鍵值的兩個對象間之比較,(比如上面的比較中加入第二個標準:第二個鍵值的大小)就會被決定使用在原先數據次序中的條目,當作一個同分決賽。然而,要記住這種次序通常牽涉到額外的空間負擔。
冒泡排序
冒泡排序(英語:Bubble Sort)是一種簡單的排序算法。它重復地遍歷要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。遍歷數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。
冒泡排序算法的運作如下:
比較相鄰的元素。如果第一個比第二個大(升序),就交換他們兩個。
對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對。這步做完后,最后的元素會是最大的數。
針對所有的元素重復以上的步驟,除了最后一個。
持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。
冒泡排序的分析
交換過程圖示(第一次):
那么我們需要進行n-1次冒泡過程,每次對應的比較次數如下圖所示:
我們先分析下標
首先要確定第一個for循環的范圍肯定是從0到n-1,但是我們使用的是游標無需到最后一個數字,只需要到達倒數第二個數字即可,故應該是n-2個數字,但有考慮到時range( )函數,故范圍是(0,n-1)。
我們走完第一個for循環,是不是相當于把最大的那個數字排放到了最后,然后我們還要尋找第二大、第三大的數字,這肯定也需要一個循環。
j | 范圍 |
---|---|
0 | (0,n-1) |
1 | (0,n-2) |
2 | (0,n-3) |
依次類推,故完整代碼如下:
def bubble_sort(alist):
n = len(alist)
for j in range(n-1):
for i in range(0,n-1-j):
if alist[i]>alist[i+1]:
alist[i],alist[i+1] = alist[i+1],alist[i]
alist = [9,12,3,23,14,45,32]
bubble_sort(alist)
print(alist)
其實還可以這么寫:
def bubble_sort(alist):
for j in range(len(alist)-1,0,-1):
for i in range(j):
if alist[i]>alist[i+1]:
alist[i],alist[i+1] = alist[i+1],alist[i]
alist = [9,12,3,23,14,45,32]
bubble_sort(alist)
print(alist)
原理都是一樣,你看著那個舒服哪個好理解就用哪個。
時間復雜度
最優時間復雜度:O(n) (表示遍歷一次發現沒有任何可以交換的元素,排序結束。)
最壞時間復雜度:O(n^2)
穩定性:穩定
最壞時間復雜度:O(n^2)很好理解,就是兩個for循環各執行n次,但這個最優化時間復雜度,就很難理解了。我直接上優化后的代碼吧。
def bubble_sort(alist):
for j in range(len(alist)-1,0,-1):
count = 0
for i in range(j):
if alist[i]>alist[i+1]:
alist[i],alist[i+1] = alist[i+1],alist[i]
count += 1
if count == 0:
break
alist = [9,12,3,23,14,45,32]
bubble_sort(alist)
print(alist)
如果第一次遍歷沒有發現任何需要剛換位置的元素,即count等于0,那么直接跳出循環。所以時間復雜度為O(n) 。
關于穩定性,無論你是比較選出最大的還是最小的始終都符合穩定性原則,比較最小的,也就是數字最小的往前面拍的。
比如這個數列有兩個93當兩個93靠近的時候,游標會自動轉到第二個93執行,所以第二個93到達了隊尾,然后再遍歷,第一個93到達了隊尾,但兩個93的前后順序不做改變。