冒泡排序python代码_Python-排序-冒泡排序-优化
這是我通過極客專欄《數據結構與算法之美》學習后的思考,分享一下,希望對你有所幫助。上一篇文章 工作后,為什么還要學習數據結構與算法 的思維導圖展現了這個專欄的內容。
說到算法中的排序,冒泡排序是最簡單的一種排序算法了,甚至不學數據結構與算法的同學都會使用它。但是你有沒有想過可以怎么優化?
什么是冒泡排序:就像水慢慢燒開,氣泡從下往上越來越大那樣,第一次循環都把n個元素中最大的元素移動至最后位置,第二次從前 n-1 個位置中找出最大元素放在最后,重復執行,直到最后結果全部有序。
最基本的算法實現,無優化版:
def bubble_sort(collection):
"""無任何優化版"""
compare_count=0
length = len(collection)
for i in range(length-1):
print(collection) #方便查看數組的排序過程
for j in range(length-1-i):
compare_count+=1
if collection[j] > collection[j+1]:
tmp = collection[j]
collection[j] = collection[j+1]
collection[j+1] = tmp
print(f"總循環次數{compare_count}")
return collection
下面來執行一下,看看執行的過程,及總循環次數:
print("bubble_sort begin.")
unsorted = [3,4,2,1,5,6,7,8]
print("bubble_sort end: ",*bubble_sort(unsorted))
執行結果如下:
bubble_sort begin.
[3, 4, 2, 1, 5, 6, 7, 8]
[3, 2, 1, 4, 5, 6, 7, 8]
[2, 1, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
總循環次數28
bubble_sort end: 1 2 3 4 5 6 7 8
通過排序的過程可以發現,在第 4 次冒泡時,數據已經有序,因此可以加入判斷,如果本次循環沒有冒泡(交換),說明數據已經有序,可以直接退出,優化后的代碼如下:
優化一
def bubble_sort2(collection):
"""如果沒有元素交換,說明數據在排序過程中已經有序,直接退出循環"""
compare_count=0
length = len(collection)
for i in range(length-1):
swapped = False
print(collection)
for j in range(length-1-i):
compare_count+=1
if collection[j] > collection[j+1]:
swapped = True
tmp = collection[j]
collection[j] = collection[j+1]
collection[j+1] = tmp
if not swapped: break # Stop iteration if the collection is sorted.
print(f"總循環次數{compare_count}")
return collection
下面來執行一下,看看執行的過程,及總循環次數:
print("bubble_sort2 begin.")
unsorted = [3,4,2,1,5,6,7,8]
print("bubble_sort2 end:",*bubble_sort2(unsorted))
執行結果如下:
bubble_sort2 begin.
[3, 4, 2, 1, 5, 6, 7, 8]
[3, 2, 1, 4, 5, 6, 7, 8]
[2, 1, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
總循環次數22
bubble_sort2 end: 1 2 3 4 5 6 7 8
至此,還有沒有其他優化方法呢? 聰明的你可能看到了,總循環次數是比較多的,僅比未優化版少了 6 次循環次數。有沒有辦法減少總循環次數呢?
觀察數據可以發現,數據已經初始有序,可以分為兩部分,無序部分 3 4 2 1 和有序部分 5 6 7 8 ,每次循環如果能夠發現無序和有序的邊界,然后下次冒泡僅對無序部分進行比較和冒泡,可大大減少比較次數(循環次數),從而加快速度。
問題是,怎么發現這個邊界呢? 第一次冒泡的過程中,第一個元素 4 被移動到下標為【3】的位置(python 列表索引從 0 開始),位置 【3】就是有序部分的開始位置。
第二次冒泡的過程中,第一個元素 3 被移動到下標為【2】的位置(python 列表索引從 0 開始),位置 【2】就是有序部分的開始位置。 ... 可以推斷出,一次冒泡的過程中,最后一個被交換的元素下標即為無序和有序的邊界,因而下次冒泡,僅對 0 ~ 邊界 的元素冒泡即可大大減少循環次數。
優化二:
def bubble_sort3(collection):
"""bubble_sort2的基礎上再優化。優化思路:在排序的過程中,數據可以從中間分為兩段,一段是無序狀態,另一段是有序狀態。每一次循環的過程中,記錄最后一個交換元素的公交車,它便是有序和無序狀態的邊界下一次僅循環到邊界即可,從而減少循環次數,達到優化。"""
compare_count=0
length = len(collection)
last_change_index = 0 #最后一個交換的位置
border = length-1 #有序和無序的分界線
for i in range(length-1):
swapped = False
print(collection)
for j in range(0,border):
compare_count+=1
if collection[j] > collection[j+1]:
swapped = True
collection[j], collection[j+1] = collection[j+1], collection[j]
last_change_index = j
if not swapped: break # Stop iteration if the collection is sorted.
border = last_change_index # 最后一個交換的位置就是邊界
print(f"總循環次數{compare_count}")
return collection
下面來執行一下,看看執行的過程,及總循環次數:
print("bubble_sort3 begin.")
unsorted = [3,4,2,1,5,6,7,8]
print("bubble_sort3 end:",*bubble_sort3(unsorted))
執行結果如下:
bubble_sort3 begin.
[3, 4, 2, 1, 5, 6, 7, 8]
[3, 2, 1, 4, 5, 6, 7, 8]
[2, 1, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
總循環次數10
bubble_sort3 end: 1 2 3 4 5 6 7 8
可以看到結果的總循環次數為 10 ,與第二版相比,循環次數減少了一倍。
冒泡排序算法的性能分析:
1、執行效率
最小時間復雜度:很好計算,最好的情況就是數據一開始就是有序的,因此一次冒泡即可完成,時間復雜度為 O(n)
最大時間復雜度:也很好計算,最壞的情況就是數據一開始就是倒序的,因此進行 n-1 次冒泡即可完成,時間復雜度為 O(n^2)
平均時間復雜度,嚴格來說平均時間復雜度就是加權平均期望時間復雜度,分析的時候要結合概率認的知識,對于包含 n 個數據的數組,有 n! 種排序方式,不同的排列方式,冒泡排序的執行時間肯定是不同的,如果要用概率認的方法定量分析平均時間復雜度,涉及的數據推理會很復雜,這里有一種思路,通過有序度和逆序度這兩個概念來分析。有序度就是有順序的元素的個數,比如 3,1 ,2 這三個數據有有序度為1 即 (1,2) 一個,相反,逆序度為 2,即(3,2)(3,1)這兩個, 1, 2, 3 這三個數據的有序度為 3:(1,2)(1,3)(2,3),逆序度為 0,完全有序的數據序列的有序度也叫滿有序度。 有個公式
逆序度 = 滿有序度 - 有序度
排序的過程就是增加有序度,減少逆序度,最后達到滿有序度,說明排序完成。逆序度也主濁元素的交換次數,最壞情況,初始狀態的有序度為 0 ,逆序度為 n*(n-1)/2 , 所以要進行 n*(n-1)/2 次交換操作,最好情況,補充狀態完全有序,逆序度為 0 不需要進行交換,這里平均交換次數我們可以取個平均值即 n*(n-1)/4。
而比較次數肯定比交換次數要多,因而平均情況下,無論算法怎么優化,時間復雜度不會低于 n*(n-1)/4,也就是 O(n^2)。
2、內存消耗
算法的內存消耗可以通過空間復雜度來衡量,冒泡排序僅需要一個變量 tmp 來儲存交換的數據,因此空間復雜度為 O(1),空間復雜度為 O(1) 的排序算法,也叫 原地排序算法
3、排序算法的穩定性
針對排序算法,有一個重要的衡量指標,就是穩定性,這個概念是說,如果待排序的序列中存在值相等的元素,經過排序之后,相等元素之間原有的先后順序不變。假如有序列 4,1,2,2,我們把第一個 2 叫 2',第二個2 叫 2'',如果排序之后,為1,2',2'',4 那么這個排序算法就是穩定的,否則就是不穩定的。穩不穩定有什么用嗎,值都是一樣的?當然有用,因為在軟件開發中,要排序的數據不單單是一個屬性的數據,而是有多個屬性的對象,假如對訂單排序,要求金額排序,訂單金額相同的情況下,按時間排序。最先想到的方法就是先對金額排序,在金額相同的訂單區間內按時間排序,理解起來不難,有沒有想過,實現起來很復雜。
但是借助穩定的排序算法,就很簡單了,先按訂單時間排一次序,再按金額排一次序就可以了。
小結
對排序算法的分析無外乎時間復雜度(最好,最壞,平均),空間復雜度,穩定性這些方面,只要理解其思路,弄明白其適用場景,不需要死記。優化思路可以通過觀察分析得出,還有一點,冒泡排序雖然使用了數組存儲數據但是并沒有使用數組隨機訪問的特性,因此改用鏈表這種存儲結構,使用冒泡排序仍然是可以實現的,你可以嘗試下。
關注個人微信公眾號 somenzz 與你一起學習。
總結
以上是生活随笔為你收集整理的冒泡排序python代码_Python-排序-冒泡排序-优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 十大品牌的集成灶如何选择,哪个性价比高?
- 下一篇: python爬大学生就业信息报告_Pyt