原文:數(shù)據(jù)結(jié)構(gòu)與算法(01):為什么要學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法
前言
集中學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法有一段時間易迹,計劃花一段時間專門記錄一下學(xué)習(xí)筆記。這篇文章想分享下自己在學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)預(yù)算法前的初衷堵泽,為什么要學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)預(yù)算法修己?我要說明一下,我也是在學(xué)習(xí)階段迎罗,有表述錯誤的地方希望看到文章的朋友可以指出來睬愤。
是因為那次,我深刻意識到了數(shù)據(jù)結(jié)構(gòu)與算法的重要性纹安。算法同事對我數(shù)據(jù)結(jié)構(gòu)做出微小的調(diào)整+簡單的算法實現(xiàn)尤辱,結(jié)果相比我之前的實現(xiàn)方式,在性能上高出數(shù)百倍厢岂,聽著一定覺得很夸張光督,到現(xiàn)在我還記得當(dāng)時我驚訝的狀態(tài)。那一刻深刻意識到它的重要性塔粒。
為什么要學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)預(yù)算法
可能很多同學(xué)會認為數(shù)據(jù)結(jié)構(gòu)與算法结借,跟操作系統(tǒng)、計算機網(wǎng)絡(luò)一樣卒茬,是脫離實際工作的知識船老,可能出了面試咖熟,這輩子也用不著?
盡管計算機專業(yè)的同學(xué)在大學(xué)期間都學(xué)習(xí)多這門課程柳畔,甚至很多培訓(xùn)機構(gòu)也會培訓(xùn)這方面的知識馍管,但是據(jù)我了解,有很多像我這樣的程序員對數(shù)據(jù)結(jié)構(gòu)和算法依舊一竅不通薪韩。還有一些人也只是聽說過數(shù)組确沸、鏈表、快排這些最基本的數(shù)據(jù)結(jié)構(gòu)和算法俘陷,稍微復(fù)雜一點的就完全沒概念了罗捎。
當(dāng)然,也有很多人說岭洲,自己實際工作中根本用不到數(shù)據(jù)結(jié)構(gòu)和算法宛逗。所以,就算不懂這塊知識盾剩,只要Java API雷激、開發(fā)框架用的熟練,照樣可以吧代碼寫的“飛”起告私。事實真的這樣嗎屎暇?
今天我來談?wù)勛约旱南敕ǎ蛘哒f學(xué)習(xí)過一段時間之后的一些心得驻粟。
想要通關(guān)大腸面試根悼,千萬別讓數(shù)據(jù)結(jié)構(gòu)和算法拖了后腿
聽說很多大公司,比如BAT蜀撑、滴滴挤巡、美團、小米酷麦、Vivo等等矿卑,面試的時候都喜歡考算法,讓人現(xiàn)場寫代碼沃饶。很多人雖然技術(shù)不錯母廷,但每次面試都會“跪”在算法上,很是可惜糊肤。那我們思考一下琴昆,為什么這些大公司都喜歡考算法呢?
還記得校招的時候馆揉,參加面試的時候业舍,我們基本上都沒啥項目經(jīng)驗,公司只能考察我們的基礎(chǔ)知識是否牢固。社招更不用說了舷暮,越是厲害的公司蟋座,越是注重考察數(shù)據(jù)結(jié)構(gòu)與算法這類基礎(chǔ)知識。我想是因為相比短期能力脚牍,他們更看重我們應(yīng)聘人的長期潛力。
可能你會說巢墅,我不懂?dāng)?shù)據(jù)結(jié)構(gòu)與算法诸狭,照樣找到了好工作啊。那我是不是就不用學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法呢君纫?當(dāng)然不是了驯遇,我們學(xué)習(xí)任何知識都是為了“用”的,是為了解決實際工作問題的蓄髓,學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)和算法自然也不例外叉庐。
不愿做一輩子CRID
如果你和我一樣只是一名業(yè)務(wù)開發(fā)工程師,可能會覺得每天主要做的就是數(shù)據(jù)庫CRID会喝,哪里用的到數(shù)據(jù)結(jié)構(gòu)與算法陡叠。是的,對于大部分的業(yè)務(wù)開發(fā)來說肢执,我們平時可能更多的是利用已經(jīng)封裝好的接口枉阵、類庫來堆砌、翻譯業(yè)務(wù)邏輯预茄,很少需要自己實現(xiàn)數(shù)據(jù)結(jié)構(gòu)和算法兴溜。但是,不需要自己實現(xiàn)并不代表我們什么都不需要了解耻陕。
如果不知道這些類庫背后的原理拙徽,不懂得時間、空間復(fù)雜度分析诗宣,我們?nèi)绾斡煤帽炫隆⒂脤λ麄儯看鎯δ硞€業(yè)務(wù)數(shù)據(jù)的時候后梧田,如何知道應(yīng)該用ArrayList還是LinkedList淳蔼?調(diào)用了某個函數(shù)之后,又改如何評估代碼的性能和資源的消耗呢裁眯?
作為業(yè)務(wù)開發(fā)鹉梨,我們會用到各種框架、中間件和底層系統(tǒng)穿稳,比如Spring存皂、RPC框架、消息中間件、Redis等等旦袋。在這些基礎(chǔ)框架中骤菠,一般都揉和了很多基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)和算法的設(shè)計思想。
比如疤孕,我們常用的Key—Value數(shù)據(jù)庫Redis中商乎,里面的有序集合是什么數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)的呢?為什么要用跳表來實現(xiàn)呢祭阀?為什么不用二叉樹呢鹉戚?
如果我們能弄明白這些底層原理,就能更好的使用他們专控。即便出現(xiàn)問題抹凳,也能夠快速的定位。因此伦腐,掌握數(shù)據(jù)結(jié)構(gòu)和算法赢底,不管對于閱讀框架源碼,還是理解其背后的設(shè)計思想柏蘑,也都是非常有用的幸冻。
在平時的工作中,數(shù)據(jù)結(jié)構(gòu)和算法的應(yīng)用到處可見辩越。再來舉個很常見的例子:如何實時地統(tǒng)計業(yè)務(wù)接口的99%響應(yīng)時間嘁扼?可能你最先想到的是每次查詢時,從小到大排序所有的限行時間黔攒,如果總共有100個數(shù)據(jù)趁啸,那第99個便是99%的相應(yīng)時間。很顯然督惰,每次用這個方法查詢的話都要排序不傅,效率是非常低下的。但是赏胚,如果知道“堆”這個數(shù)據(jù)結(jié)構(gòu)的話访娶,用連個堆可以非常高效地解決這個問題。
對于基礎(chǔ)結(jié)構(gòu)研發(fā)工程師觉阅,寫出開源水平的架構(gòu)才是他們的目標
現(xiàn)在互聯(lián)網(wǎng)上的技術(shù)文章崖疤、架構(gòu)分享、開源項目滿天飛典勇,照貓畫虎做一套基礎(chǔ)架構(gòu)框架并不難劫哼。就拿RPC框架來看。
不同的公司割笙、不同的人做出的RPC框架权烧,架構(gòu)設(shè)計思路都差不多眯亦,最后實現(xiàn)的功能也差不多。但是有的人做出來的框架般码,Bug很多妻率、性能一般、擴展性也不好板祝,只能在自己公司僅有的幾個項目里面用一下宫静。而有的人做的框架可以開源道GitHub上給更多的人用,甚至被Apache收錄券时,就好比阿里的Dubbo RPC框架囊嘉。為什么會有這么大的差距呢?
我認為革为,那些高手之間的競爭其實就在細節(jié)。這些細節(jié)包含:你用的算法是不是夠優(yōu)化舵鳞,數(shù)據(jù)存取的效率是不是夠高震檩,內(nèi)存是不是夠節(jié)省等等。這些積累起來蜓堕,決定了一個框架是不是優(yōu)秀抛虏。所以,如果你和我一樣還不懂?dāng)?shù)據(jù)結(jié)構(gòu)和算法套才,對大O復(fù)雜度分析還不是很熟練迂猴,不知道怎么分析代碼的時間復(fù)雜度和空間復(fù)雜度,這個很是說不過去背伴,也應(yīng)該趕緊補一補沸毁。
對編程有追求,不想被行業(yè)淘汰
什么是編程能力強傻寂,是代碼的可讀性好息尺、健壯?還是擴展性好疾掰?我覺得沒辦法給出一個明確的標準搂誉,也列不全,因為可以衡量的指標是在是太多了静檬。但是炭懊,在我看來,性能好壞起碼是其中一個非常重要的評判標準拂檩。但是侮腹,如果我們連代碼的時間復(fù)雜度、空間復(fù)雜度都不知道怎么分析广恢,又怎么能寫出高性能的代碼呢?
可能有人和我之前想法差不多凯旋,我現(xiàn)在的業(yè)務(wù),用戶量很少,需要處理的數(shù)據(jù)量也很少至非,開發(fā)中不需要考慮那么多性能的問題钠署,完成功能是最主要的,用什么數(shù)據(jù)結(jié)構(gòu)和算法荒椭,差別不是很大谐鼎。但是當(dāng)我接觸到千萬級數(shù)據(jù)處理,甚至億級數(shù)據(jù)的時候我傻眼了趣惠。內(nèi)存溢出等問題接踵而來的時候狸棍,我慌了,當(dāng)時我完全拿他沒辦法味悄,因為我的知識儲備有限草戈。我記得很清楚,當(dāng)時找了一個專門做算法的同事侍瑟,請求他的支援唐片,他在了解了我的需求后給出了一套自己的算法實現(xiàn)方案,我試過了涨颜,結(jié)果讓我很難受费韭,問題解決了,而且結(jié)果完全超出我的預(yù)期庭瑰,甚至是驚訝星持,但我還是很難過,難過的是我自己之前忽視數(shù)據(jù)結(jié)構(gòu)這塊弹灭。他給的方案其實都是我熟悉的幾種常用數(shù)據(jù)結(jié)構(gòu)督暂,只是在先后順序上做了調(diào)整,和算法思路上給出了一點提示穷吮,結(jié)果性能好不夸張的說损痰,高出我之前的百倍。也是那次事情時候酒来,我才下定決心要集中的學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法卢未,并且要高度重視它。
其實做業(yè)務(wù)開發(fā)的同學(xué)幾年下來都會有這樣的感覺堰汉,一樣事情做久了辽社,一個公司待久了,會發(fā)現(xiàn)我們每天做的都是重復(fù)的事情翘鸭〉吻Γ可能讓你寫一份自己的簡歷,都可以寫七八個項目就乓,但明顯能看的出來項目之間的技術(shù)架構(gòu)汉匙、實現(xiàn)技術(shù)方案都大同小異拱烁,或者說我們的能力并沒有跟著項目經(jīng)驗的增加而出現(xiàn)大的提升。所以我覺得數(shù)據(jù)結(jié)構(gòu)與算法這個東西我們不去學(xué)噩翠,可能真的一輩子都喲弄不到戏自,也感受不到它的好,它的強大之處伤锚。但是一旦掌握擅笔,你就會常常被他的強大威力所折服。
內(nèi)容總結(jié)
其實寫這篇文章屯援,單純?yōu)榱朔窒硪幌伦约旱南敕兔牵M麑Ω乙粯拥某绦騿T們對數(shù)據(jù)結(jié)構(gòu)與算法的認識能夠引起高度重視。我們的目的是建立時間復(fù)雜度狞洋、空間復(fù)雜度意識弯淘,寫出高質(zhì)量的代碼,能夠設(shè)計基礎(chǔ)加固吉懊,提成編程技能耳胎,訓(xùn)練邏輯思維,積攢人生經(jīng)驗惕它,以此獲得工作回報,實現(xiàn)我們的價值废登。
更多個人文章:RelaxHeart網(wǎng) - Tec博客