排序>>交換排序>>氣泡排序
List:
1 2 3 4 5 |
0.概念+虛擬碼+示例分析 1.基本氣泡排序 2.氣泡排序改進1 3.氣泡排序改進2——區域性氣泡排序 4.Question |
- start
基本概念:
維基百科http://zh.wikipedia.org/wiki/%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F
虛擬碼:(來自百科)
1 2 3 4 5 6 7 8 9 |
function bubblesort (A : list[1..n]) { var int i, j; for i from n downto 1 { for j from 0 to i-1 { if (A[j] > A[j+1]) swap(A[j], A[j+1]) } } } |
簡要排序過程的示例:(基本氣泡排序)
初始陣列
1 |
[50, 10, 30, 20, 40, 60] |
第一輪:
1 2 3 4 5 |
cmp 50 10 -> change [10, 50, 30, 20, 40, 60] cmp 50 30 -> change [10, 30, 50, 20, 40, 60] cmp 50 20 -> change [10, 30, 20, 50, 40, 60] cmp 50 40 -> change [10, 30, 20, 40, 50, 60] cmp 50 60 -> nochange |
第二輪:
1 2 3 4 5 |
[10, 30, 20, 40, 50, 60] cmp 10 30 -> nochange cmp 30 20 -> change [10, 20, 30, 40, 50, 60] cmp 30 40 -> nochange cmp 40 50 -> nochange |
第三輪
1 2 3 4 |
[10, 20, 30, 40, 50, 60] cmp 10 20 -> nochange cmp 20 30 -> nochange cmp 30 40 -> nochange |
第四輪:
1 2 3 |
[10, 20, 30, 40, 50, 60] cmp 10 20 -> nochange cmp 20 30 -> nochange |
第五輪:
1 2 3 |
[10, 20, 30, 40, 50, 60] cmp 10 20 -> nochange [10, 20, 30, 40, 50, 60] |
cmp count 15
即共進行n-1=5輪冒泡,比較次數為 (n-1) + (n-2) + ……+1 =n*(n-1)/2=15
- start
基本氣泡排序python實現:
1 2 3 4 5 6 7 8 9 10 |
#氣泡排序,base def bubble(l): print l for i in range(len(l)-1,0,-1): #每一輪冒泡,第 i個 元素會是最大的(i for j in range(i): #從0到i-1,比較 current 和next,若current > next,對換 if l[j] > l[j+1]: l[j], l[j+1] = l[j+1], l[j] print l |
- start
問題:在基本氣泡排序的示例中,第三輪結束時,其實已經排序完成了,但是還是一直會持續後面幾輪的排序,這就帶來了無謂的浪費.
改進:加入標誌,判斷,若是上一輪不存在資料交換,代表上一輪已經是排序的了,退出
比較次數:12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#改進1: 當某一輪跑完,不存在資料交換時,代表已排序完成,此時退出 def bubble_improve(l): flag = 1 #初始標誌,1 for i in range(len(l)-1,0,-1): #若是上一輪存在資料交換,繼續執行排序 if flag: flag = 0 #每一輪初始,交換標誌為0 for j in range(i): if l[j] > l[j+1]: l[j], l[j+1] = l[j+1], l[j] flag = 1 #存在交換,標誌置為1 print l #否則,代表目前序列已經排序完畢了 else: break |
- start
區域性氣泡排序:(資料不多,不知道自己理解對不對)
序列[ a b c d ] 冒泡到了b,此時a小於b,比較b c,若是 b 大於 c,交換b c 得到 [ a c b d ]
通常氣泡排序一直往前,繼續比較b和d
其實,在完成一次資料交換時(bc),可以反向增加一次比較,(a 和 c) ,若是a>c,再次交換得到[ c a b d] ——反向做一次冒泡
(百度百科有幾行….湊合看)
定義:可以在一趟全域性掃描中,對每一反序資料對進行區域性氣泡排序處理,稱之為區域性氣泡排序
區域性氣泡排序與氣泡排序演算法具有相同的時間複雜度,並且在正序和逆序的情況下,所需的關鍵字的比較次數和移動次數完全相同。
由於區域性氣泡排序和氣泡排序的資料移動次數總是相同的,而區域性氣泡排序所需關鍵字的比較次數常少於氣泡排序,這意味著區域性氣泡排序很可能在平均比較次數上對氣泡排序有所改進
當比較次數較少的優點不足以抵消其程式複雜度所帶來的額外開銷,而當資料量較大時,區域性氣泡排序的時間效能則明顯優於氣泡排序
(檢視百度百科,有張對比圖)
簡而言之,正向冒泡時,若存在資料交換,反向再進行一次冒泡比較。減少了比較次數
why?
假設在第二輪冒泡 到了50 30
1 2 3 4 |
[10, 20, 40, 50, 30, 60] 帶標誌位冒泡:cmp 50 30 ->change [10, 20, 40, 30, 50, 60] count+=1 第三輪 count+= 4 (10,20) (20,40) (40,30) (40,50) 第四輪count +3 (10,20) (20,30) (30,40) (無資料交換了,退出) |
共 8次
1 2 3 |
區域性冒泡: cmp 50 30 ->change [10, 20, 40, 30, 50, 60] count+=1 cmp 40 30 -> change [10, 20, 30, 40, 50, 60] count+=1 第三輪 count+=4(無資料交換了,退出) |
共 6次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#改進2: 區域性氣泡排序 def bubble_improve2(l): print l flag = 1 scope = len(l)-1 for i in range(scope,0,-1): if flag: flag = 0 for j in range(i): inner_flag = 0 #本次是否存在資料交換標誌,每次置空,不復用flag的原因是如果第一次就交換了,會造成不必要的區域性冒泡 if l[j] > l[j+1]: l[j], l[j+1] = l[j+1], l[j] flag = 1 inner_flag = 1 #從前往後的冒泡,j與j+1發生資料交換了,反向冒泡 j-1 j #若是本輪存在資料交換,區域性排序處理 j-1 j j+1,保證是從小到大的 if inner_flag: if j - 1 > 0: if l[j-1] > l[j]: l[j-1], l[j] = l[j],l[j-1] print l else: break |
區域性氣泡排序一個示例過程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[50, 10, 30, 20, 40, 60] cmp 50 10 -> change [10, 50, 30, 20, 40, 60] cmp 50 30 -> change [10, 30, 50, 20, 40, 60] cmp 50 20 -> change [10, 30, 20, 50, 40, 60] inner cmp 30 20 inner change [10, 20, 30, 50, 40, 60] cmp 50 40 -> change [10, 20, 30, 40, 50, 60] inner cmp 30 40 cmp 50 60 -> nochange [10, 20, 30, 40, 50, 60] cmp 10 20 -> nochange cmp 20 30 -> nochange cmp 30 40 -> nochange cmp 40 50 -> nochange [10, 20, 30, 40, 50, 60] |
- start
僅是貼出來,權當複習,木有答案,後續補充
A.氣泡排序概念,過程描述?
B.最差,平均,最優 時間複雜度?
C.空間複雜度?
D.是否是穩定排序?
E.如何改進?
F.區域性氣泡排序原理?
G.適用場景,什麼情況下最優,什麼情況下最差?
—————————————– END ————————————————-
P.S.
這是第一篇,有什麼不對請指正哈,歡迎補充任何問題和答案
白天上班加班(SDET),夜深敲程式碼(python,java…….),會堅持寫完的
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式