轉載於知乎
:http://www.zhihu.com/question/20066988/answer/26968999
一般來說,數據結構和算法這本書上提到的任何算法/數據結構,你都不會有機會重新實現一次。
因為,早有就各種各樣的庫,對外提供了工業級的、充分泛化的實現,只需拿來用就是了。
重寫的話,一個代碼質量/執行速度,顯然都極難超過經過千錘百煉的、在無數項目中經過充分測試的庫實現;另一個,書上都是為了教學而做的簡化實現,實際使用中,需要對算法做一定的泛化。(比如,c的qsort庫函數,只要保證數據是以指針數組索引的、對自定義數據須傳入比較大小的功能函數,那么任何數據都可以用這個qsort算法排序;C++里面呢,則是和容器、迭代器之類東西結合通盤考慮的,可泛用於任何符合規范的容器和原生數據類型。而課本上的實現,僅能支持數組中的整數。想做到工業水平,沒有足夠的經驗是不可能的。)
但,另一方面,所有這些算法/數據結構的設計思路,卻會貫穿於絕大部分項目之中。
比如說,簡單的冒泡算法,它是不是只是“多次掃描一個數組,交換遇到的每一對相鄰的、順序反了的數字;當不再發生交換時,數組已完成排序”甚至”好不容易才死記硬背下來的一段代碼“?
如果你只學會了這個,那么,你真就完全白學了。
作為一個表現一般的排序算法,冒泡排序本身出場率就不高;何況還有各種提供了泛化的sort算法的庫:如果僅僅記下了這個,那么你一輩子都不會遇到”必須重寫冒泡算法“的場合。
但,如果你把冒泡算法記成:
就好象水中的氣泡一樣,每次只執行“相鄰的元素比較密度(或其它特征),密度小的上浮,密度大的下沉”這個局部物理過程;多次進行后,局部有序就會變成(相關特征上的)整體有序。
甚至:
模仿各種會導致整體有序現象的局部過程去處理數據,可以使得數據整體上滿足類似的排布。
甚至:
考察任何自然規律,看它會產生什么有趣的后果;那么當需要達到類似的效果時,不妨嘗試用程序模擬出這個規律,很可能就已經得到了想要的效果。
那,你這一生,可就受用不盡了。
比如說,”高大上“的”神經網絡“”遺傳算法“”蟻群算法“等等等等,其實骨子里不都是這個”冒泡思路“嗎?
類似的,各種樹都是鏈表的”鈎掛“思想+數組的”索引“思想的結合體;”模擬退火算法“又是冒泡思路結出來的另一顆果子;音頻濾波算法就是簡諧振動計算公式;面向對象的”繼承“不過是常見的”歸一化“手法的另一個表述方式……
可以說,如果能像對冒泡算法的真正理解一樣,徹底弄明白各種算法的設計思路並加以借鑒,那么你對這個世界的各種規律了解的有多透徹,你的程序就可以寫的有多靈動。
一旦掌握這個,從此,你再不必像那些菜鳥一樣,絞盡腦汁敲出無數代碼去”湊“需求;而是只需用代碼編織出需要的規律,然后丟給CPU執行,你真正想要的東西就會自然”涌現“:現在,你只要找出”結果已經出現“的識別方法,用它來結束你的邏輯就行了。
(當然,達成一個目的往往可以有多個不同的途徑,不同途徑利用不同的規律;那么哪個途徑最優呢?算法課教過你:這就是所謂的“算法復雜度”)
——冒泡算法可不就是用代碼編織了一個”數值大者靠前(或靠后)“的規律,然后丟給CPU一跑,一大片數據就有序了?
——遺傳算法呢,不正是”抄襲“了自然界的自然選擇規律嗎?把這個規律丟給CPU一跑,居然連AI都弄出來了!
這些只是一些特別經典、特別著名的案例而已。
實際工作中,也是時刻都可能遇到一些新鮮的需求/場景;要完成工作,除了出苦力一行行碼代碼外,一樣可以通過觀察找到其中的規律,然后用代碼編織規律,再讓這些規律去替你完成需求:后者往往會比前者簡潔的多得多,執行速度一般也會快得多得多。
這類隨時隨地“發明”的算法實在不值一提,不能讓你像那些著名案例一樣一舉成名;但它們卻實實在在可以提高你的工作效率,讓其他人望塵莫及。
——經常有高手驕傲的宣稱,別人幾萬、幾十萬行代碼都解決不了的問題,他數百行代碼就清楚漂亮的解決了,執行效率還高出許多倍:他們就是這樣做到的。