1. 程式人生 > >關於演算法學習的總結和感悟

關於演算法學習的總結和感悟

時隔一年重讀《演算法導論》,去年讀到了二叉查詢樹就擱淺了,今年從頭撿起,希望能走的 更遠一些。算上大學時的資料結構與演算法課,今年可以算是第三波學習攻勢了。隨著學習的深入, 對演算法的學習漸漸有了些自己的看法和感悟。 一.為什麼學習演算法? 記得初學演算法時不明白為什麼費力分析程式的執行步驟後,還要用公式表達出來並求極值。 一遍遍的學習漸漸有了領悟:演算法研究是用來做大事的!之所以分析效率還求極限,是因為 各種演算法和資料結構都要研究其在海量輸入資料或最壞最不利的情況下的效率表現。如果 只是我們每天乏味工作中那三兩個數的排序,幾十個數值對的雜湊,那其實怎樣實現都無所 謂了。 所以個人覺得,學習演算法能提高分析程式碼、洞察效率的能力,並且它也是我們繼續深入學習 作業系統、網路程式設計、資料庫的基礎。如作業系統管理記憶體的紅黑樹,儲存程序優先順序的 最大堆,程式執行時函式呼叫的棧結構,資料庫中的B樹索引,大量資料的外部多路歸併排序 和編譯器將表示式解析為樹然後遍歷等等。所以要想深入電腦科學的核心,演算法這一關是 必須過的,這也是我的學習計劃。 是在整個知識體系的最底層部分,這是我巨集偉藍圖的基礎,呵呵~ 如果你學了感覺它沒用,其實不是那樣的,只是你還沒碰到需要它的場合,殺雞焉用牛刀, 記住它是用來做大事情! 二.演算法的學習方法
學習演算法如果選擇好方法學到最後很可能就什麼都不記得了,就像我第一次讀《演算法導論》時 一樣,也仔仔細細的看了,還做了些習題,可讀完過後感覺什麼都沒掌握一樣。這次重讀,我 找到了適合自己的方法: 1.《演算法導論》中幾乎每個資料結構與演算法都會有對應的例子和圖示用來生動講解。光看一遍 還不夠,拿起筆跟著例子走一遍演算法的虛擬碼,看看演算法每一步中的值、狀態是怎麼變化的。 這樣才能把例子搞透,不然白瞎了《演算法導論》裡一幅幅那麼清楚明瞭的圖示了。 2.搞懂例子,自然就要實現演算法了。不管演算法多麼簡單,一定要自己動手實現,切忌手懶啊。 實現好一個個演算法的程式碼都儲存備份好,這也是一筆財富,而且很有成就感。 關於具體用什麼 語言來實現稍後再說。 3.只是搞清楚了基本的演算法還不夠,《演算法導論》每節後還有不少有價值的習題,特別是每章 最後都有一些思考題,其中有的是資料結構進行擴充套件的,有的是演算法的實際應用,一定要好好 研究才能更深的理解這一節的知識。 4.最後一定要記筆記,不管是手寫的還是部落格。筆記不僅方便以後的查詢,記筆記的過程也會 激發你大腦思考,很多奇思妙想都是動筆頭時冒出來的。 記住:學習並不浪費時間,浪費時間的是重複學習
三.實現語言的選擇 大學時的資料結構課要求使用的是C++,後來我第一遍學《演算法導論》時用的是我最習慣的 Java,而現在第二遍學習時我用的卻是C。不用我最熟悉的Java而用C的原因是C語言的簡潔 和指標的強大,這一點在實現複雜一些的資料結構時體現的尤為突出。並且很多底層的東西 如作業系統、編譯器等也都是C的地盤,因此同時學習C語言和演算法對未來的深入學習有著 極為重要的作用。暫時放下我的老朋友Java,擁抱C! 四.要把握本質 初學演算法時,搞不清楚為什麼有那麼多的資料結構,那麼多的排序演算法。散列表不是已經很好 了嗎,為什麼又搞出一堆二叉樹?快排不是已經很完美了嗎,為什麼還有堆排、冒泡、合併排? 一遍遍地學習,學會比較各種資料結構和演算法後,才能看清這些的設計背後的本質。 1.各種排序
快速排序的確很完美了,但其他排序方法也是有他們的用武之地的。對於輸入資料範圍已知時, 如輸入資料都是0到10之間的整數,那麼計數排序就可以上場了。又如當輸入資料是海量的, 沒法一次全部拿到記憶體中排好時,可以將輸入資料分成多塊,每塊拿到記憶體中排序,之後對每 個排好序的塊進行多路歸併。 2.堆、棧及連結串列 堆、棧、連結串列都是再簡單不過的資料結構了,但我們學習時不能就侷限於對簡單應用的掌握, 這些簡單結構在特定場景或與其他資料結構結合起來使用時會產生巨大的威力。如堆在K路 歸併中與其他內排序的配合,用棧來實現遞迴呼叫(如二叉樹的非遞迴中序遍歷)等。 3.雜湊與紅黑 散列表效能很好,可是當需要隨時動態插入資料時,隨著資料越來越多,散列表中的衝突資料 也越來越多,這樣的靜態雜湊自然要效能下降。可是紅黑樹卻可以保證樹的高度從而保證效率, 所以儘管紅黑樹很複雜,但它卻是維護動態集合的不錯選擇。然而散列表也是與時俱進的, 動態雜湊能夠在散列表中資料增多到一定量時自動增大散列表,並重新雜湊。這就需要較大的 儲存空間,但現今的記憶體白菜價,所以散列表也可以維護動態資料集合了,所以memcached火 起來了。 4.樹家族 平衡樹家族很龐大,有AVL樹、紅黑樹、Treap樹以及Size平衡樹(SBT)。但學習時要把握住 他們的本質:他們都是平衡二叉樹,區別只是在如何保持樹的高度不會過高上。為何關注樹的 高度?因為平衡二叉樹上各種操作的效能都是由樹高來決定的。 此外常見的還有基數樹和Trie樹。在樹結點中儲存01或者各種字元,用於排序01串以及文字統計。 五.演算法的等級修煉  我心中對演算法有個模糊的分級,學習時可以設定自己短期或長期想要達到的目標。 現在快要第二次學完《演算法導論》基礎部分的十四章了,也只是瞭解的程度,才剛剛開始有些 感悟。都說演算法是內功,學習起來需要曠日持久、小火慢熬,所以還要努力啊! 1.瞭解:瞭解各種演算法和資料結構的基礎知識,但對他們的具體應用範圍一頭霧水。 2.掌握:能夠清楚明白各種演算法的優劣,並開始學會比較他們的應用場景。 3.選擇:至此各種結構與演算法已經在我們的錦囊裡了,碰到問題時要學會從中拿出合適的。 4.擴充套件:根據具體問題對現有演算法進行簡單的擴充套件和改造,並進行效率分析。 5.設計:能為現實生活中複雜的問題設計全新的資料結構或演算法來解決。 結束語 演算法是美妙而迷人的,但越深入就需要越強的數學功底。每個人可以根據自己的興趣濃淡、 個人能力為自己制定目標。我自知自己沒有那麼強的能力,所以個人制定目標等級是3和4 之間,也就是能夠應用這些現有的資料結構和演算法,能簡單的擴充套件和分析就可以了。希望 大家也都能為自己制定合適的目標,重要的是享受演算法的學習過程。切忌走火入魔啊,哈哈!