創(chuàng)作時間:2019-03-17
作者:周林
版權(quán)所有,轉(zhuǎn)載請聯(lián)系作者獲取授權(quán)、并注明作者與出處
? ? ? ? ? ? ??
寫在前面的話
??????在互聯(lián)網(wǎng)、大數(shù)據(jù)、人工智能火爆的今天,“算法”這個詞幾乎婦孺皆知,業(yè)已成為“高薪”“牛X”的代名詞。應(yīng)不少朋友的邀請,特連載本系列,旨在用最通俗的方式——“講人話、無廢話、看得懂、用得上”——將位于神龕之上的算法送進(jìn)尋常百姓家。 本篇作為系列的第一篇,采用“What、Why、How”文章結(jié)構(gòu),來給大家普及一下算法的基本概念(也糾正一些朋友的錯誤概念)。
?What is Algorithm?(算法是個什么鬼 )
?????? 為了不落入俗套,本文不會重復(fù)wiki上“算法”的官方定義,而采用啟發(fā)式結(jié)構(gòu)來闡述算法的本質(zhì):試想平時在遇到問題的時候,我們是如何解決的。
???????樸素而廣泛的過程方法論如下:
????? ?1. 重新定義問題,結(jié)構(gòu)化描述
?????? 2. 根據(jù)重定義,歸類問題
?????? 3. 根據(jù)問題類別,做經(jīng)驗匹配
?????? 4. 根據(jù)匹配結(jié)果,分支處理:若匹配,采用經(jīng)驗方法;若匹配不上,設(shè)計開發(fā)新方法
?????? 5. 迭代更新經(jīng)驗庫,增強(qiáng)面向未來問題的能力 與算法相關(guān)的就是上面的第3步~第5步。
?????? 簡單來說,算法本質(zhì)是:解決某類問題的方法。
?????? 如果方法已經(jīng)在經(jīng)驗庫里了,直接拿來主義,也就是“既有算法”;如果不在,那么設(shè)計開發(fā)的新方法,新方法就是“新算法”。當(dāng)然還有一種情況:雖然經(jīng)驗庫里有針對該類問題的方法了,但是設(shè)計開發(fā)了一個更有效的新方法,那么也稱為“新算法”。 下面來對幾個關(guān)鍵點進(jìn)行闡述:
什么是“更有效的算法”?
????? “更有效”的背后邏輯其實比較的就是“代價”,或者稱為“開銷”。經(jīng)濟(jì)上衡量就是成本,它分為兩個維度:時間成本和資源成本。
???????資源成本在計算機(jī)上的體現(xiàn)就是硬盤、內(nèi)存、CPU等一系列硬件資源開銷。對這些硬件資源開銷進(jìn)一步抽象,就是空間成本。從學(xué)科分類上講,算法其實屬于計算數(shù)學(xué),計算數(shù)學(xué)屬于應(yīng)用數(shù)學(xué)。用專業(yè)術(shù)語來描述時間成本與空間成本,就是計算復(fù)雜度,很自然地,它也有兩個維度:時間復(fù)雜度和空間復(fù)雜度。描述復(fù)雜度的數(shù)學(xué)符號是O()。后面我們會詳細(xì)介紹O()的表達(dá)。
??????綜上所述,所謂的“更有效”的算法,指的就是時間復(fù)雜度或者空間復(fù)雜度更優(yōu)的算法。
為什么要“重新定義問題,結(jié)構(gòu)化描述”?
?????? 把人腦也看做一臺機(jī)器的話,很顯然這臺機(jī)器的運(yùn)行方式和效率與計算機(jī)有所不同(盡管現(xiàn)在的機(jī)器學(xué)習(xí)在盡可能地模擬人腦的機(jī)理,但是兩者至少在現(xiàn)階段還有本質(zhì)不同)。人腦在連續(xù)信號和非結(jié)構(gòu)化場景下的處理能力是卓越的,但是計算機(jī)只能處理離散信號,并且必須最終轉(zhuǎn)化成結(jié)構(gòu)化數(shù)據(jù)才能進(jìn)行處理(盡管現(xiàn)在的機(jī)器學(xué)習(xí)可以通過自我學(xué)習(xí)來將數(shù)據(jù)結(jié)構(gòu)化)。用一張圖來描述這個過程就是:
Why to use Algorithm?(算法有什么鬼用)
?????? 從上面對解決現(xiàn)實問題的過程方法論的描述中,其實已經(jīng)可以看出算法的價值就在于:經(jīng)驗的重用。套用一句IT行話就是“不要重復(fù)制造輪子”。
?????? 好了,既然現(xiàn)在你已經(jīng)對算法有了大致的感性認(rèn)識,那么接下來根據(jù)人類的學(xué)習(xí)習(xí)慣,就來看看抽象的算法概念,在現(xiàn)實里到底“長什么模樣”。
?????? 很多人認(rèn)為“算法 = 程序或者程序”,這其實是一個狹義的理解。如前面所說的,算法的本質(zhì)是解決某類問題的方法,而程序或者代碼只是方法的一種表達(dá)形式而已。你也可以用自然語言或者偽代碼來進(jìn)行表達(dá)算法。
算法的“模樣”(應(yīng)對電燈不工作的算法——代碼方式):
public STATUS_CODE lamp_issue_handler() {
?? STATUS_CODE ret_val = UNKNOWN_ISSUE;
?? ?if (!isPowerOn(this)) {
????? ret_val = powerOn(this) ? NOT_POWER_ON_ISSUE : POWER_ISSE;
??? } else if(!isBulbCrash(this)) {
????? ret_val = replaceBulb(this) ? BULB_CRASH_ISSUE : REPLACE_ISSUE;
??? } else {
??????ret_val = fixBulb(this) ? BULB_FIXABLE_ISSUE : FIX_FAILURE_ISSUE;
??? }
??? return ret_val;
}
算法的“模樣”(應(yīng)對電燈不工作的算法——自然語言方式):
????? 首先檢查電源是否接好了:沒有接好,接上。
????? 如果接上了仍然不工作,看看燈泡是否燒壞了:
????????????? 如果是,換個新燈泡;
????????????? 如果燈泡沒有燒壞,修理燈泡
算法的“模樣”(應(yīng)對電燈不工作的算法——流程圖方式):
How to use Algorithm?(如何使用算法)
????????算法的本質(zhì)就是方法,計既然是方法,就是一系列的操作;既然是操作,就必然有作用對象。
??????? 在軟件程序設(shè)計中,這樣的作用對象就是“數(shù)據(jù)結(jié)構(gòu)”。
?????? 怎么來理解數(shù)據(jù)結(jié)構(gòu)呢?
???????前面我們講到了,解決問題的第一步就是要將問題結(jié)構(gòu)化描述。結(jié)構(gòu)化描述的本質(zhì)就是利用一系列便于操作的“基礎(chǔ)元素”來表達(dá)。
???????那么怎樣的“基礎(chǔ)元素”是便于操作的呢? 首先我們要清楚,操作的主體是誰。從上一段的闡述來看,這個主體貌似是算法,但是我們注意,算法不是憑空運(yùn)行的,是要在計算機(jī)上運(yùn)行的,所以歸根結(jié)底,操作的主體是計算機(jī)。所以,這里所謂的“便于操作”指的是便于計算機(jī)運(yùn)行。
?????? 計算機(jī)運(yùn)行有兩個維度:硬件維度和軟件維度。
?????? 從硬件維度看:學(xué)過計算機(jī)組成原理就知道,程序是在計算機(jī)的CPU高速緩存和內(nèi)存中運(yùn)行的。對應(yīng)的存儲結(jié)構(gòu),通常都是線性的。為了充分提升線性結(jié)構(gòu)的性能優(yōu)勢,硬件廠商(如CPU廠商)在設(shè)計硬件時,就抽象了針對一些結(jié)構(gòu)(如堆棧)的操作(如壓棧、出棧),所以很自然地,這樣的結(jié)構(gòu)就應(yīng)該作為數(shù)據(jù)結(jié)構(gòu)。
????? ?從軟件維度看:我們編寫的應(yīng)用程序一般不會直接運(yùn)行在硬件之上,而是運(yùn)行在操作系統(tǒng)、運(yùn)行時或者虛擬機(jī)(如JVM)之上。所以操作系統(tǒng)、運(yùn)行時或者虛擬機(jī)已經(jīng)抽象的結(jié)構(gòu)(如數(shù)組、隊列、樹、圖等),也應(yīng)該作為數(shù)據(jù)結(jié)構(gòu)。
????? ?上面贅述了這么多,其實就是要表達(dá)一個觀點:算法是要配合數(shù)據(jù)結(jié)構(gòu)的,拋開數(shù)據(jù)結(jié)構(gòu)談算法就是無源之水、無根之樹。
??????? 看到這里,我想你一定徹底明白,為什么圖靈獎得主尼古拉斯·沃斯會提出那個著名的等式了:程序 = 算法 + 數(shù)據(jù)結(jié)構(gòu)。
寫在最后的話
??????? 看到這里,相信你已經(jīng)對算法這個概念已經(jīng)不再陌生,它對于你而言也不再高高在上。 無論在大學(xué)學(xué)習(xí),還是在工作中,大家都幾乎被一種說法反復(fù)洗腦:算法非常重要,它是計算機(jī)的靈魂。在這里,我想糾正一下這個錯誤的觀點。
?????? 首先,廣義的算法不僅僅只是軟件算法;
???????再次,計算機(jī)系統(tǒng)不僅僅只是由軟件構(gòu)成,還有硬件。
???????硬件涉及到材料科學(xué)、制造工藝等一系列技術(shù),這些是不能簡單被算法替代的。
?????? 所以,脫離上下文、一味強(qiáng)調(diào)算法的重要性是耍流氓。
本原創(chuàng)系列同步在以下自媒體上更新,敬請關(guān)注: