1. 冒泡排序原理
不斷比較兩個相鄰的元素,將較大的元素交換到右邊(升序)
2. 過程
1.比較第1個數和第2個數,較大的放在右邊
2.比較第2個數和第3個數,較大的放在右邊
… …
n-1.比較第(n-1)個數和第n個數,較大的放在右邊
直到最後兩個數比較完,整個數列的最大值已位於最右邊(最大值就像水中的氣泡一樣,一直升到最右邊)
至此,一個比較批次執行完畢,目的只是將未排序數列的最大值移到最右邊。還要繼續執行下一個批次,將剩餘數字的最大值移到最右邊,直到執行完所有批次。
一直重複上述步驟,不停的把未排序數列中的最大值放到右邊,最終整個數列排序完成。
3. 代碼實現
def bubble_sort1(our_list):
lenght = len(our_list)
# 批次外循環,有多少個數,循環多少次
for i in range(lenght):
# 批次內循環,目的是將未排序數列的最大值移到最右邊
for j in range(lenght - 1):
# 比較相鄰兩個數
if our_list[j] > our_list[j+1]:
# 交換
our_list[j], our_list[j+1] = our_list[j+1], our_list[j]
return our_list
4. 優化改進
4.1 外循環,判斷數列是否已有序
對於原始算法,外循環,無論數列是否有序,都要循環 lenght 次,即使是[1,2,3,4,5,6]這樣的數列。
所以優化增加了對內循環是否發生了元素交換
的判斷,如未交換,則證明數列已有序,程序應停止。從而減少了循環次數,效率增加。
優化代碼:
def bubble_sort_check_swapped(our_list):
has_swapped = True
while(has_swapped):
has_swapped = False
for i in range(len(our_list) - 1):
if our_list[i] > our_list[i+1]:
our_list[i], our_list[i+1] = our_list[i+1], our_list[i]
has_swapped = True
return our_list
4.2 內循環,有序的部分不再操作
對於原始算法,批次內的每次循環,無論數列是否有序,都要把所有相鄰元素都比較一遍,即使是[9,2,7,14,15,16]這樣的數列,後面的[14,15,16]也要比較。
所以優化增加了無序數列的長度標記,每執行一輪內循環,需比較數列的長度減1。
def bubble_sort_ignore_done(our_list):
has_swapped = True
num_of_iterations = 0
while(has_swapped):
has_swapped = False
for i in range(len(our_list) - num_of_iterations - 1):
if our_list[i] > our_list[i+1]:
our_list[i], our_list[i+1] = our_list[i+1], our_list[i]
has_swapped = True
num_of_iterations += 1
return our_list
形象理解
將外循環和內循環比作兩個人,Boss 和 Worker,外循環叫Boss,內循環叫Worker。
Worker 需要對高低不同的貨物進行排序,方法就是每次比較兩個相鄰的元素,將較大的元素交換到右邊,但 Worker 每走一趟都要回來向 Boss 報告這一趟比較完了,Worker 得到 Boss 的命令後再比較下一趟。
未優化時 Worker 機械無腦的比較兩個相鄰的元素,並將較大的元素交換到右邊,Boss 也機械無腦的同意 Worker 進行下一趟比較,一切都機械無腦的井井有條,但效率低下。
對於 4.1 的優化,經過長時間的工作,Worker發現了“偷懶”的祕訣,不僅可以加快工作效率,也使自己不會那麼累。祕訣就是,對於已經比較完的貨物,就不再比較,走到這裏就可以回去了。
對於 4.2 的優化,Boss 也發現了加快工作效率的方法。每次命令 Worker 去比較的時候,先看一下貨物是否有序,如有序則無需比較,任務完成。