當前位置: 華文問答 > 數位

在校生為了面試,有必要強行記住一些復雜演算法如紅黑樹、KMP等的實作嗎?

2015-10-07數位

quora上有道類似的問題,問的是如何才能增強數據結構和演算法的能力,robert love(【Linux Kernel Development】的作者)的答案我認為寫得非常好,其中也回答了題主的「是否需要背下來rbtree的實作」,連結在這裏:Robert Love's answer to How do I strengthen my knowledge of data structures and algorithms?。簡要轉譯如下:
-----
現在的學生學習和理解數據結構的方法有問題。

數據結構的良好基礎不是對每個數據結構都知道細節怎麽實作,都背下來大O復雜度和攤銷復雜度,當然知道這些非常好,只是你在工作中很少用到它們,你的職業生涯裏幾乎不可能讓你實作一個紅黑樹的節點刪除演算法。但是!!你必須知道什麽時候BST對於一個問題是個有效的解法。

所以,兩個建議:
1. 視覺化數據結構,把它畫出來,在你的腦海中視覺化,可以更好地幫助你直觀地理解它。(推薦兩個數據結構視覺化網站:Data Structure Visualization 和 VisuAlgo - visualising data structures and algorithms through animation)
2. 學習什麽時候以及如何將不同的數據結構運用到自己的程式碼裏。忘掉細枝末節的東西,而更關註:什麽時候需要hash?什麽時候需要tree?什麽時候最小化堆是正確的答案?

演算法學習推薦:演算法導論
演算法具體實作書籍:Algorithms in C++, ALgorithms in Java
-----

robert的回答給了一個很好的思路,不僅在數據數據結構這門課上可以套用,也可以幫助在其它一些基礎課的學習上,我談一下自己的理解:

學習作業系統,需要理解為什麽會有OS這個東西,如何沒有OS會怎麽樣;OS提供給使用者哪些抽象、它又是怎麽管理硬體的;行程是怎麽管理和排程的,死結是怎麽產生和解決的,記憶體是怎麽管理,檔案系統有什麽用以及是如何實作的,最好再就一個具體的作業系統(比如xv6)研究這些原理是怎麽套用的;而不是開機啟動的詳細步驟,當然你知道最好。

學習電腦組成原理,需要理解的是為什麽在這個高級語言泛濫的時代我們還需要學習組譯,電腦是如何一步一步發展到如今這個組成結構的,為什麽單周期實作的cpu效率不高,之後的流水線cpu是如何改進單周期的以及其設計中的挑戰是什麽,由流水線引發的hazard有哪些以及怎麽處理,forwarding又是怎麽實作;而不需要背下來每一級流水線寄存器是哪些,因為現代cpu實作一般都是15級以上的流水線stage,除非你是cpu設計者否則背了根本沒用。

學習電腦體系結構,需要理解常用的並列方法,並知道每一種並列方法裏的具體手段,比如instruction-level parallelism中,需要理解Instruction pipelining,Out-of-order execution,Register renaming,Speculative execution等技術到底幹了什麽達到改善的目的,知道這些的目的是為了幫助你在程式裏合理地組織程式碼和數據來最好地發揮CPU功能,而不是為了讓你設計一個新的CPU。另外,處理器設計中包括了許多工程實踐中的很好的原則,學習它可以幫助你理解和解決別的領域的問題。

學習編譯原理,需要理解的是一個編譯器實作的幾個步驟(詞法分析、語法分析、語意分析、執行時環境、中間程式碼、程式碼生成、程式碼最佳化)以及一些關鍵演算法。學詞法分析你需要理解狀態機、學語法分析你至少需要知道LL自頂向下和LR自底向上的演算法,以及為什麽需要把我們的程式轉成抽象語法樹。學執行時環境需要理解程式是怎麽儲存、裝載和執行的。程式碼最佳化的時候需要知道最常見的最佳化方法。

學習電腦網路,需要理解的是整個全球互聯網是怎麽運作的以及5層模型(套用層、傳輸層、網路層、數據鏈路層、實體層)中上層和下層是怎麽互動的。可能對大部份開發者有用的是套用層和傳輸層TCP/UDP的原理,重點是TCP原理的理解:為什麽TCP是一個可靠協定?它為了「可靠」付出了什麽代價?TCP為什麽要握3次手而不是4次5次6次?為什麽結束TCP連線需要4次揮手而不是5次6次?TCP的重傳機制是怎麽實作的?為什麽要引入滑動視窗的概念?以及需要理解Congestion control的核心演算法是怎樣的。

學習資料庫原理,重點不是讓你知道sql怎麽寫,而是讓你理解如何設計正確的schema,在這個過程中為了消除數據冗余、插入/刪除/修改異常會逼著你理解那幾種範式(1NF、2NF,3NF,BCNF),以及思考一個功能完整、效率高的資料庫是怎麽實作,重點是原理的學習,比如在學習transaction的ACID性質的時候,這四點分別代表什麽意思,以及是怎麽實作它們的?如何實作一個高效的資料庫這個話題就太大了,不展開了。

總結一下,為了讓自己更高效地學習這些課,介紹一個我一直在用的方法,就是在學習這些課的同時,不斷地問自己,「這個設計/演算法為什麽是這樣的,而不是那樣的。如果讓我來解決這個問題,我會怎麽做」。

update:

大一大二電腦相關專業的新生很容易搞不清楚這些基礎課程的關系,導致學得非常累。其實,這些基礎課不是電腦領域這張大地圖上零散的點,它們可以透過「抽象」來實作「分層」,「分層」的目的是讓你更容易看清楚這些課的關系,我寫過一個回答來解釋這個事情:https://www. zhihu.com/question/1962 8851/answer/305960909 ,希望對初學者有幫助。

歡迎關註公眾號,非週期性分享工作、職場、生活和個人感悟: