當今世界最為經典的十大演算法 投票進行時
當今世界最為經典的十大演算法--投票進行時
作者:July、時間:二零一一年三月七日。參考:十三個經典演算法研究與總結、目錄+索引,本人第一大原創作品。
內容說明:I、 本文原名為:當今世界最受人們重視的十大經典演算法,後改為如上題目。II、本文分為倆部分: 第一部分、來自聖經的十大演算法:為某網友票選出來的十個來自聖經的演算法。 第二部分、當今世界最為經典的十大演算法--投票進行時:是懇請本文的讀者為您心目中當今世界最為經典的演算法投上一票,最終在本BLOG內票選產生當今世界最為經典的十大演算法(投票截止日期,三年後的此刻,即二零一四年三月七日)。非常感謝大家。----------------------------------------
第一部分、來自聖經的十大演算法
當今世界,已經被發現或創造的經典演算法數不勝數。如果,一定要投票選出你最看重的十大演算法,你會作何選擇列?有國外網友在StackExchange上發起過投票,讓人們投票選出心目中最為經典的演算法,最終產生了下面得票數最高的十大經典演算法(投票數統計截止到2011年3月7日):
第十名:Huffman coding(霍夫曼編碼) 霍夫曼編碼(Huffman Coding)是一種編碼方式,是一種用於無損資料壓縮的熵編碼(權編碼)演算法。1952年,David A. Huffman在麻省理工攻讀博士時所發明的,並發表於《一種構建極小多餘編碼的方法》(A Method for the Construction of Minimum-Redundancy Codes)一文。
第九名:Binary Search (二分查詢) 在一個有序的集合中查詢元素,可以使用二分查詢演算法,也叫二分搜尋。二分查詢演算法先比較位於集合中間位置的元素與鍵的大小,有三種情況(假設集合是從小到大排列的): 1.鍵小於中間位置的元素,則匹配元素必在左邊(如果有的話),於是對左邊的區域應用二分搜尋。 2.鍵等於中間位置的元素,所以元素找到。 3.鍵大於中間位置的元素,則匹配元素必在右邊(如果有的話),於是對右邊的區域應用二分搜尋。另外,當集合為空,則代表找不到。
第八名:Miller-Rabin作的類似的試驗測試 這個想法是利用素數的性質(如使用費馬大定理)的小概率尋找見證不數素數。如果沒有證據是足夠的隨機檢驗後發現,這一數字為素數。
第七名:Depth First Search、Breadth First Search(深度、廣度優先搜尋) 它們是許多其他演算法的基礎。關於深度、廣度優先搜尋演算法的具體介紹,請參考此文:教你通透徹底理解:BFS和DFS優先搜尋演算法。
第六名:Gentry's Fully Homomorphic Encryption Scheme(紳士完全同態加密機制)演算法。 此演算法很漂亮,它允許第三方執行任意加密資料運算得不到私鑰(不是很瞭解)。
第五名:Floyd-Warshall all-pairs最短路徑演算法 關於此演算法的介紹,可參考我寫的此文:幾個最短路徑演算法比較(http://blog.csdn.net/v_JULY_v/archive/2011/02/12/6181485.aspx)。d[]: 二維陣列. d[i,j]最小花費、或最短路徑的鄰邊。
for k from 1 to n: for i from 1 to n: for j from 1 to n: d[i,j] = min(d[i,j], d[i,k] + d[k,j])
第四名:Quicksort(快速排序) 快速排序演算法幾乎涵蓋了所有經典演算法的所有榜單。它曾獲選二十世紀最偉大的十大演算法(參考這:細數二十世紀最偉大的10大演算法)。關於快速排序演算法的具體介紹,請參考我寫的這篇文章:一之續、快速排序演算法的深入分析,及十二、一之再續:快速排序演算法之所有版本的c/c++實現。
第三名:BFPRT 演算法 1973 年,Blum、Floyd、Pratt、Rivest、Tarjan一起釋出了一篇名為 “Time bounds for selection” 的論文,給出了一種在陣列中選出第k大元素平均複雜度為O(N)的演算法,俗稱"中位數之中位數演算法"。這個演算法依靠一種精心設計的 pivot 選取方法,即選取中位數的中位數作為樞紐元,從而保證了在最情況下的也能做到線性時間的複雜度,打敗了平均O(N*logN)、最壞 O(n^2) 複雜度的快速排序演算法。
事實上,這個所謂的BFPRT,就是本blog中闡述過的快速選擇SELECT演算法,詳情請參考下列博文:第三章、尋找最小的k個數、十四、快速選擇SELECT演算法的深入分析與實現。在我的這兩篇文章中,給出了此快速選擇SELECT演算法,藉助選取陣列中中位數的中位數作為樞紐元,能做到最壞情況下執行時間為O(N)的複雜度的證明。
我在這裡簡單介紹下在陣列中選出第k大元素的時間複雜度為O(N)的演算法: 類似快排中的分割演算法:
每次分割後都能返回樞紐點在陣列中的位置s,然後比較s與k的大小若大的話,則再次遞迴劃分array[s..n],小的話,就遞迴array[left...s-1] //s為中間樞紐點元素。否則返回array[s],就是partition中返回的值。 //就是要找到這個s。
找到符合要求的s值後,再遍歷輸出比s小的那一邊的元素。
各位還可參考在:演算法導論上,第九章中,以期望線性時間做選擇,有尋找陣列中第k小的元素的,平均時間複雜度為O(N)的證明。原程式隨機選取陣列中某一元素作為樞紐元,最後可證得程式的期望執行時間為O(n),且假定元素是不同的。
第二名:Knuth-Morris-Pratt字串匹配演算法 關於此演算法的介紹,請參考此文:六、教你從頭到尾徹底理解KMP算法。KMP演算法曾經落選於二十世紀最偉大的十大演算法,但人們顯然不能接受,如此漂亮、高效的KMP演算法竟然會落選。所以,此次最終投票產出生,KMP演算法排到了第二名。
第一名:Union-find
並查集是一種樹型的資料結構,用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。常常在使用中以森林來表示。集就是讓每個元素構成一個單元素的集合,並就是按一定順序將屬於同一組的元素所在的集合合併。並行查詢,最終佔據了此份榜單的第一名。
第二部分、當今世界最為經典的十大演算法--投票進行時 怎麼樣,上文那些投票產生出來的來自聖經的演算法,你是否熟悉?或者,如果要您選出您心目中,當今世界最為經典的十大演算法,您肯定也、絕對不一定認同上述十個所謂來自聖經的演算法便是當今世界最為經典的十大演算法,對吧?ok,那麼,現在,我給你一個投票權,你會把票投給哪一個演算法列?好的,咱們也來一次投票吧,請把你的意見,決定權寫在本文下面的評論裡。
我把已經產生的前十名的演算法,再寫在下面,方便投票(投票截止日期:三年後的今天,即二零一四年三月七日):
一、Huffman coding(霍夫曼編碼)。二、Binary Search (二分查詢)。三、Miller-Rabin作的類似的試驗測試。四、Depth First Search(深度優先搜尋)。五、紳士完全同態加密機制六、Floyd-Warshall all-pairs最短路徑演算法。七、Quicksort(快速排序)。八、BFPRT 演算法。九、Knuth-Morris-Pratt字串匹配演算法。十、Union-find。
為了讓大家有更多的選擇,我再貼出其它幾種同樣經典但暫時未能排進上述榜單前十名的候選演算法:
十二、linear programming,線性規劃。
十四、Merge Sort。歸併排序。十五、Ford–Fulkerson演算法。網路最大流演算法。十六、輾轉相除法。 在數學中,輾轉相除法,又稱歐幾里得演算法,是求最大公約數的演算法,即求兩個正整數之最大公因子的演算法。此演算法作為TAOCP第一個演算法被闡述,足見此演算法被重視的程度。它是已知最古老的演算法, 其可追溯至3000年前。輾轉相除法首次出現於歐幾里得的《幾何原本》(第VII卷,命題i和ii)中,而在中國則可以追溯至東漢出現的《九章算術》。擴充套件的輾轉相除法則構造性地證明了,對任意整數a和b ,存在一對x、y使得 ax + by = gcd(a, b) 。
十七、RSA加密演演算法。一種加密演算法,日後再做詳細介紹。十八、遺傳演算法。可參考本人寫的關於GA 演算法的這篇文章:七、遺傳演算法 透析GA本質。
十九、最大期望(EM)演算法。 此演算法入選資料探勘領域十大經典演算法。在統計計算中,最大期望(EM)演算法是在概率(probabilistic)模型中尋找引數最大似然估計的演算法,其中概率模型依賴於無法觀測的隱藏變數(Latent Variable)。最大期望經常用在機器學習和計算機視覺的資料聚類(Data Clustering)領域。最大期望演算法經過兩個步驟交替進行計算,第一步是計算期望(E),利用對隱藏變數的現有估計值,計算其最大似然估計值;第二步是最大化(M),最大化在 E 步上求得的最大似然值來計算引數的值。M 步上找到的引數估計值被用於下一個 E 步計算中,這個過程不斷交替進行。
二十、資料壓縮 資料壓縮是通過減少計算機中所儲存資料或者通訊傳播中資料的冗餘度,達到增大資料密度,最終使資料的儲存空間減少的技術。資料壓縮在檔案儲存和分散式系統領域有著十分廣泛的應用。資料壓縮也代表著尺寸媒介容量的增大和網路頻寬的擴充套件。
二十一、Hash函式 Hash,一般翻譯做“雜湊”,也有直接音譯為“雜湊”的,就是把任意長度的輸入(又叫做預對映, pre-image),通過雜湊演算法,變換成固定長度的輸出,該輸出就是雜湊值。關於hash表的詳細闡述,請參考此篇文章:十一、從頭到尾徹底解析Hash表演算法。
二十二、Dynamic Programming(動態規劃)。關於動態規劃的粗略介紹,請參考此文:三、dynamic programming。
二十三、堆排序演算法。 堆排序演算法作為一種快速穩定的演算法,其平均時間複雜度(最壞也為)O(n*lgn)。當然,在實際應用中,一個實現的好的快速排序演算法仍然要優於堆排序演算法。不過,堆資料結構還可以作為高效的優先順序佇列。對堆排序演算法作簡單瞭解,可參考這:堆排序演算法。
二十四、遞迴與回溯演算法。此倆個演算法,相信各位比較熟悉,在此不做贅述。
二十五、最長公共子序列 最長公共子序列,英文縮寫為LCS(Longest Common Subsequence)。其定義是,一個數列 S ,如果分別是兩個或多個已知數列的子序列,且是所有符合此條件序列中最長的,則 S 稱為已知序列的最長公共子序列。動態規劃的一個計算最長公共子序列的方法如下: 以兩個序列 X、Y 為例子:設有二維陣列 f[i][j] 表示 X 的 i 位和 Y 的 j 位之前的最長公共子序列的長度,則有:
f[1][1] = same(1,1) f[i][j] = max{f[i-1][j-1]+same(i,j),f[i-1][j],f[i][j-1]}
其中,same(a,b)當 X 的第 a 位與 Y 的第 b 位完全相同時為“1”,否則為“0”。此時,f[i][j]中最大的數便是 X 和 Y 的最長公共子序列的長度,依據該陣列回溯,便可找出最長公共子序列。
該演算法的空間、時間複雜度均為O(n2),經過優化後,空間複雜度可為O(n),時間複雜度為O(nlogn)。更多詳情,參見之前寫的一篇拙文(不過,鑑於寫的糟,日後會重寫):三、dynamic programming。
二十六、紅黑樹的演算法與實現 關於紅黑樹,linux核心中有實現,本BLOG內也已經寫了6篇紅黑樹系列的文章。且,本BLOG內的此紅黑樹系列,總計六篇文章,是整個國內有史以來有關紅黑樹的最具代表性,最具完整性,最具參考價值的資料。詳情,請參考:五(續)、教你透徹瞭解紅黑樹,及紅黑樹的c++完整實現原始碼。
二十七、A*搜尋演算法。 相對於BFS、Dijkstra 等演算法,A*搜尋演算法作為一種高效的最短路徑搜尋演算法,如今,已得到日益廣泛的應用。初步瞭解A*搜尋演算法的高效及與其它最短路徑演算法的比較,請參考此文:一(續)、A*,Dijkstra,BFS演算法效能比較及A*演算法的應用。
二十八、影象特徵提取與匹配之SIFT演算法 sift,尺度不變特徵轉換,是一種電腦視覺的演算法用來偵測與描述影像中的區域性性特徵,它在空間尺度中尋找極值點,並提取出其位置、尺度、旋轉不變數,此演算法由 David Lowe 在1999年所發表,2004年完善總結。關於此演算法,請參考如下,粗略介紹:九、影象特徵提取與匹配之SIFT算法,利用第三方庫編譯過程:九(續)、sift演算法的編譯與實現,c語言一步一步實現sift演算法:九之再續:一步一步用c語言實現sift演算法、上,及九之再續:教你一步一步用c語言實現sift演算法、下。
候選經典演算法一直在不斷增補中,估計最後能達到上100種。...
還猶豫什麼列?快投上您寶貴的一票吧。每人可投多次票,只要您認為哪個演算法是最為經典的演算法,您就在下面的評論裡寫上它的序號,及演算法名稱。 當然,如果上文中不曾出現你認為最經典的演算法,你也可以寫在評論裡,為你鍾愛的它投上一票。而後我將考慮您的意見,把您鍾愛的演算法也作為一種候選演算法,添補上去。:D。 最後,我們自己來做一份十大經典演算法的排名榜單,也讓世界各地的人看看我們中國人的意見。怎麼樣,還猶豫什麼列,趕緊評論、趕緊投票吧... 更新:
- 由於諸多事情,未能抽空給各位投了票的朋友傳送本部落格全部博文集錦的檔案,若各位等不及日後待我一一傳送的話 July、二零一一年十月二十四日凌晨。
本BLOG版權宣告、即日生效: 1、本人和CSDN對本BLOG內所有任何一切內容和文章,享有版權。如需轉載,請註明出處及作者本人。 2、凡是轉載本BLOG內任何文章和內容的個人,或網站,一律不註明出處者,本人將永久追蹤、永久譴責、永久追究法律責任的一切權利。謝謝。July、二零一一年三月七日,即日起生效。