Coco學程式設計(三)--冒泡就是折騰 (轉)
Coco:好久不見,真想大家。由於某人的懶惰,嚴重影響到到我的人氣啊。
我:還好意思說,前段時間我本來是感冒,卻讓你宣揚成了“某種未知的呼吸傳染病”,害得我差點被隔離。
Coco:不把你隔離起來,怎麼能讓你老老實實的寫文章?
我:隔離我也認了,你居然會造謠說我的病會在qq染,難道你要我被隔離到一個不能上網的地方嗎?什麼時候聽說過人類的傳染病會能過網際網路傳染了?
Coco:所以說我說你中的是呀~
我:@#$%^
什麼時候人能中CIH了~
Coco:不可能嗎?
我:可能嗎?
Coco:不可能嗎?
我:可能嗎?
Coco:不可能嗎?
我:可能嗎?
Coco:我只是探討一下,不要那麼激動嘛,不可能嗎?
我:要是我哪天我能中了CIH,乾脆找人把我格式化了重灌算了。
Coco:別忘了裝套,都說這東東好,我還沒用過呢。
我:喂喂喂,我們再這麼胡扯下去,篇幅就都被浪費啦。
Coco:好吧好吧,戴上口罩,繼續工作。這次我們玩兒什麼?
(玩……還真是一語中的啊,本來要把你包裝成一個積極向上的好青年的,這下大家都知道你學是為了好玩兒了……)
我:我們這次玩兒……不對,是要學習一個很親切的排序演算法,氣泡排序。
Coco:這個~是不是太簡單了?好像很多人寫過Hello World之後第二個就是這個東東了。
我:這倒是不假,氣泡排序的特點就是實現非常簡單,基本上所有有流程控制能力的語言都可以實現它,而且也非常容易學習,可以說這是演算法課的“Hello World”。在Python中的實現也不會比其它語言更復雜。現在你寫一個冒泡來對我們一直用的示例陣列排序吧。
Coco:沒有你的日子裡,我寂寞無聊中,自己寫了一些程式,其中就包括這個冒泡~
我:喂~,不要說得那麼肉麻好不好?讓人以為我們有什麼不可告人的關係……先把程式拿來給我看看。
:namespace prefix = o ns = "urn:schemas--com::office" />
def BubSort(theInput):
#c = 0
#e = 0
for i in range(len(theInput)):
for j in range(1, len(theInput) - i):
if theInput[j-1] > theInput[j]:
theInput[j-1], theInput[j] = theInput[j], theInput[j-1]
#e = e + 1
#c = c + 1
#print c
#print e
return
#Follow is the demo of Bubble up sort.
Array=[6, 16, 10, 9, 15, 5, 11, 1, 19, 4, 14, 17, 18, 0, 13, 3, 12, 2, 8, 7]
print Array
BubSort(Array)
print Array
Coco:那些註釋中的程式碼好像與我無關啊?
我:這是我給你加上的。你的程式碼本身沒什麼問題,執行良好。我加上這些程式碼是為了計算一下排序中進行了多少次操作。只要把關於c的程式碼行註釋符去掉,就可以計算發生了多少次,把關於e的程式碼行註釋符去掉,就可以計算生髮生了多少次比較。
Coco:好像很方便的樣子,我試試嘍。才20個元素的列表,應居要190次比較和108次交換啊。
我:事實上,在這個程式中,比較次數只和元素的個數有關,N個元素的比較次數就是N*(N+1)/2。即使是一個完全排好序,不需要再進行交換的陣列。
Coco:我用[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]試試……還真是這樣子呢。這豈不是做了很多無用功?
我:是呀,針對這個問題,你有沒有什麼好辦法呢?
Coco:我想,可以記住每次遍歷中最後一次發生交換的位置,下次搜尋到這個位置為止就好了,我在程式里加一個標誌試試。
def MrkBubSort(theInput):
# c = 0
# e = 0
i = 0
bottom = len(theInput)
while i < bottom:
i = 0
M = True
for j in range(1, bottom):
if theInput[j-1] > theInput[j]:
theInput[j-1], theInput[j] = theInput[j], theInput[j-1]
M = False
bottom = j
# e = e + 1
# c = c + 1
if M:
break
i = i + 1
# print c
# print e
return
#Follow is the demo of Bubble up sort.
Array=[6, 16, 10, 9, 15, 5, 11, 1, 19, 4, 14, 17, 18, 0, 13, 3, 12, 2, 8, 7]
print Array
MrkBubSort(Array)
print Array
Coco:把註釋掉的計數程式碼拿出來執行後可以知道,對同樣的這個陣列,發生了178次比較,確是少了一些啊。
我:如果你試一試一些“極端”的資料,會觀察到一些有趣的現像。比如 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0],[19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18],[19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]等等。
Coco:以下是輸出結果,每一組輸出結果中,第一組是原陣列,下一行的單個整數是比較次數,下一個是交換次數,最後一行的陣列是排序後的。
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
19
0
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>>
>>> [19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
190
190
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0]
190
19
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>>
>>> [19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
37
19
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
Coco:的確是有一些問題,比如,如果陣列的未尾存在逆序,即使前面的資料已經排好,也一樣需要190次交換。有沒有什麼辦法解決它呢?
我:提示一下,如果逆序在開頭呢?
Coco:嗯,只需要37次比較。看來比較次數和操作的方向有關。
我:所以,如果從兩端交替進行排序,就可以儘可能的避免無謂的比較操作。這種演算法我們稱為搖動。你試試實現它吧。
(很長時間後……)
def ShkBubSort(theInput):
c = 0
e = 0
l = len(theInput)
tmpt = 1
top = 0
tmpb = l
bottom = tmpb
while top < bottom:
if top < tmpt:
top = tmpt
else :
top = top + 1
bottom = tmpb
M = True
for j in range(top, bottom):
if theInput[j-1] > theInput[j]:
theInput[j-1], theInput[j] = theInput[j], theInput[j-1]
M = False
tmpb = j
e = e + 1
c = c + 1
if M:
break
for k in range(top + 1, bottom):
cur = l - k
if theInput[cur - 1] > theInput[cur]:
theInput[cur-1], theInput[cur] = theInput[cur], theInput[cur-1]
M = False
tmpt = cur
e = e + 1
c = c + 1
if M:
break
# print top, bottom
print c
print e
return
Coco:比我想像的麻煩的多啊。實際效果如何呢?我試試。
>>> [19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
54
19
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [6, 16, 10, 9, 15, 5, 11, 1, 19, 4, 14, 17, 18, 0, 13, 3, 12, 2, 8, 7]
169
108
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>>
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0]
54
19
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
190
190
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
Coco:總的來說,好像有些改進,不過並不是很明顯噢。
我:實際上,最關鍵的是,不論如何改進,都不會改變這一系列演算法交換操作過多的缺點。而在排序操作中,寫操作的代價要遠高於讀操作,所以無論怎樣減少比較次數,都不能真正有效的提高排序的。
Coco:唉,費這麼大勁,學了一個不甚實用的演算法,真是瞎折騰……
我:當然,學習這個演算法……
Coco:OK,OK,我知道你要說,主要是為了讓我練習,不過現在每個月只露一次面,無論多複雜的程式,也不能真正有效的提高我的熟練程度啊。你是不是也應該勤勞一些呀~
我:事實上,這個月我可沒有讓大家空等。我一直在寫《 Story》的第十一集,現在基本上已經解決了所有的問題,很快就會完成。
Coco:唉~,那裡又沒有機會讓我出場,失望啊,不知道哪天才能和大家再見面了,我會想你們的……
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-957938/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 不要太折騰程式
- 折騰Java設計模式之命令模式Java設計模式
- Coco學程式設計(二)--直接選擇排序 (轉)程式設計排序
- 折騰Java設計模式之中介者模式Java設計模式
- 折騰Java設計模式之觀察者模式Java設計模式
- 折騰Java設計模式之狀態模式Java設計模式
- 折騰Java設計模式之模板方法模式Java設計模式
- 折騰Java設計模式之單例模式Java設計模式單例
- 折騰Java設計模式之建造者模式Java設計模式
- 資料中心運維:減少折騰就是降低故障運維
- Coco學程式設計--《設計模式》,語言無關的好書 (轉)程式設計設計模式
- 折騰Java設計模式之備忘錄模式Java設計模式
- 折騰Java設計模式之直譯器模式Java設計模式
- Linux折騰Linux
- 折騰日記
- waydroid折騰
- 《Windows 程式設計》學習筆記(三) (轉)Windows程式設計筆記
- Hackintosh (黑蘋果) 折騰蘋果
- 折騰樹莓派樹莓派
- UGNX折騰筆記筆記
- 【折騰】github+jekyll搭建靜態網站(還沒折騰完),折騰不下去了,求解救Github網站
- 10年工齡的90後程式設計師折騰部落格的這些年程式設計師
- 小白折騰伺服器(三):docker-compose+Dockerfile伺服器Docker
- 從學生到程式設計師(三) 關於學習 (轉)程式設計師
- 程式設計修養(三) (轉)程式設計
- nvim 折騰筆記 2筆記
- 程式設計,就是要輕鬆程式設計
- Startbbs YouBBS等輕論壇程式折騰過程
- 折騰筆記[2]-跨平臺打包tauri程式筆記
- 我就是程式,程式就是我嗎? (轉)
- 一個遊戲已經設計了三年,如今我們到底折騰出個什麼名堂來?遊戲
- Linux程式設計之三(轉)Linux程式設計
- VS Code折騰記 - (1)扯淡
- 折騰oracle的em3Oracle
- 折騰oracle的em2Oracle
- 折騰oracle的em1Oracle
- hexo fluid主題折騰HexoUI
- 多虧風變程式設計,讓我找到了人生轉折點!程式設計