排序與搜索——冒泡排序

排序與搜索

排序算法(英語: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的前后順序不做改變。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 排序算法基礎 排序算法,是一種能將一串數據按照特定的排序方式進行排列的一種算法,一個排序算法的好壞,主要從時間復雜...
    jackyshan閱讀 4,010評論 3 11
  • 排序(上):為什么插入排序比冒泡排序更受歡迎? 排序對于任何一個程序員來說,可能都不會陌生。你學的第一個算法,可能...
    GhostintheCode閱讀 3,381評論 4 27
  • 一、對比分析圖 均按從小到大排列 k代表數值中的"數位"個數 n代表數據規模 m代表數據的最大值減最小值 穩定性:...
    leo567閱讀 1,252評論 0 1
  • 概述 排序有內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部...
    蟻前閱讀 5,215評論 0 52
  • 第一期線下活動完美收官,感謝各位媽媽的信任與支持,感謝孩子們的勇于挑戰、無限探索的精神!望大家多提寶貴意見,...
    漁你同行閱讀 921評論 0 0