上次我們介紹了資料結構中的堆疊問題,今天來介紹一下演算法。世界上有沒有「最好的」演算法呢?在評價「最好」之前,還是要加一些限制條件,比如是一般條件下最好,還是惡劣條件下最好。
在南京三牌樓,如果要去南京站,一般情況下是要從玄武湖隧道通過的,但是如果那裡發生了一些意外,基本上動都動不了的。如果選擇從玄武湖公園穿過去(東西不多的話),可以在這極端情況下趕上火車。所以,世界上沒有絕對的好。
講到排序,目前世界上通常情況下最好的演算法是一種叫做「快速排序」的演算法。由英國計算機科學家托尼霍爾想到的。那麼為啥這麼快呢?因為它強調少做事情。
首先,對於一大堆無序的數字,從中隨機挑選乙個數字,比如是33,這個被隨機選上的數字被稱為是樞值,接下來,將所有要排序的數字分成兩部分,第一部分是大於等於33的,第二部分是小於樞值33的,在第一步完成後,一大堆無序的數字就變得稍微有序一點了。
(小於33的數)33(大於33的數)
第二步,從上面得到的兩堆數字,分別採用第一步的方法各自再找乙個樞值。對於第一堆,由於所有數字都比33大,至少也等於33,因此,第二次隨機挑選的樞值肯定也是乙個大於33的數字,比如70;類似的,對於第二堆,由於所有的數字都小於33,因此第二次隨機挑選的樞值都肯定小於他,比如6。接下來,再把兩隊數字各自分成大於等於相應樞值的數字序列,以及小於樞值的數字序列。這樣,原來的一大堆數就變成了4小堆。
(小於6的)6(大於6小於33的)33(大於33小於70的)70(大於70的)
在接下來,用同樣的方法,四堆變八堆,八堆變十六堆,很快所有的數字就排好序了。
這種演算法通常情況下複雜度是nlog(n),比選擇排序,氣泡排序快的多。
假如有乙個學區,裡面有20000名高中學生,如果讓大家到乙個超級大的學校上大課,再從中挑出學生中的尖子,效率肯定低。如果事先劃出幾個分數線,根據個人成績的高低把20000名學生分到十所學校,第一所學校裡的學生成績最好,第十所最差,再找出尖子生,就容易了,這就是快速排序的原理。
以下是我們對10,5,2,3,41,38,96進行排序的**:
def
quicksort
(array):
if len(array) < 2:
return array #為空或只包含乙個元素的陣列是「有序」的
else:
pivot = array[0] #樞值條件
less = [i for i in array[1:] if i <= pivot]#由所有小於樞值的元素組成的子列表
greater = [i for i in array[1:] if i > pivot]#由所有大於樞值的元素組成的字列表
return quicksort(less) + [pivot] + quicksort(greater)
print(quicksort([10,5,2,3,41,38,96]))
快速排序是通常情況下最好的演算法,但是,在極端情況下,他的複雜度是n平方,和氣泡排序一樣糟糕,世上沒有絕對的好。
把快速排序帶入到我們日常生活中來,可以幫助我們有效地辨別事情的輕重緩急,學做減法。把事情依照「重要/不重要」和「緊急/不緊急」兩個維度,劃分成四個象限,這是很多時間管理的書籍會提供的工具。然而我們需要把每件事情從頭考量,評斷後再分類,就又浪費了很多時間在規劃上。
更有效的辦法就是我們的快速排序。
首先找到乙個顯而易見的待辦事項(樞紐),接著綜合考慮急迫性和重要性,分成兩撥。
再給兩撥事情找樞紐,就把所有的工作依照評分分成4份了。
在接下來,快速檢查後兩部分的事情,將不必要的事做減法刪除,將重要但不急迫的事情先預定計畫。然後專注完成前兩部分的事情,通過排序和減法,一天要完成的工作就剩下了一半。
樞紐這個節點,幫我們樹立了參考點,事情一件件單看,很難取捨;但是有了參考,一比較就能掂量差別,我們就可以勇敢做減法了。
演算法 排序演算法之快速排序
很受打擊啊啊啊啊啊!這道排序題我很久之前就做過,而且當時沒用20分鐘就搞定了,可是,今天在公司做完手上的活之後打算刷題時,又心血來潮的想重做一遍,心想反正也花不了多少時間,結果。血崩了。要求 對於乙個int陣列,請編寫乙個快速排序演算法,對陣列元素排序。給定乙個int陣列a及陣列的大小n,請返回排序...
演算法 排序演算法之快速排序
快速排序是由東尼 霍爾所發展的一種排序演算法。在平均狀況下,排序 n 個專案要 nlogn 次比較。在最壞狀況下則需要 n2 次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他 nlogn 演算法更快,因為它的內部迴圈 inner loop 可以在大部分的架構上很有效率地被實現出來。快速排序...
排序演算法之快速排序
快速排序使用分治法 divide and conquer 策略來把乙個序列 list 分為兩個子串行 sub lists 步驟為 從數列中挑出乙個元素,稱為 基準 pivot 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面 相同的數可以到任一邊 在這個分割槽退出...