算法+數據結構(第01篇)走下神壇吧!算法

算法+數據結構(第01篇)走下神壇吧!算法

引言

在互聯網、大數據、人工智能火爆的今天,“算法”這個詞幾乎婦孺皆知,業已成為“高薪”“牛X”的代名詞。

應不少朋友的邀請,特連載本系列,旨在用最通俗的方式——“”講人話、無廢話、看得懂、用得上“”——將位於神龕之上的算法送進尋常百姓家。

本篇作為系列的第一篇,採用“What、Why、How”文章結構,來給大家普及一下算法的基本概念(也糾正一些朋友的錯誤概念)。

What is Algorithm?(算法是個什麼鬼 )


為了不落入俗套,本文不會重複wiki上“算法”的官方定義,而採用啟發式結構來闡述算法的本質,試想平時在遇到問題的時候,我們是如何解決的。

樸素而廣泛的過程方法論如下:

1. 重新定義問題,結構化描述

2. 根據重定義,歸類問題

3. 根據問題類別,做經驗匹配

4. 根據匹配結果,分支處理:若匹配,採用經驗方法;若匹配不上,設計開發新方法

5. 迭代更新經驗庫,增強面向未來問題的能力

與算法相關的就是上面的第3步~第5步。

簡單來說,算法本質是:解決某類問題的方法。如果方法已經在經驗庫裡了,直接拿來主義,也就是“既有算法”;如果不在,那麼設計開發的新方法,新方法就是“新算法”。

當然還有一種情況:雖然經驗庫裡有針對該類問題的方法了,但是設計開發了一個更有效的新方法,那麼也稱為“新算法”。下面來對幾個關鍵點進行闡述!!!

什麼是“更有效的算法”?

“更有效”的背後邏輯其實比較的就是“代價”,或者稱為“開銷”。經濟上衡量就是成本,它分為兩個維度:時間成本和資源成本。

資源成本在計算機上的體現就是硬盤、內存、CPU等一系列硬件資源開銷。對這些硬件資源開銷進一步抽象,就是空間成本。

算法其實從學科分類上講,屬於計算數學,計算數學屬於應用數學。用學科術語來描述時間成本與空間成本,就是計算複雜度,很自然地,它也有兩個維度:時間複雜度和空間複雜度。描述複雜度的數學符號是O()。後面我們會詳細介紹O()的表達。

綜上所述,所謂的“更有效”的算法,指的就是時間複雜度或者空間複雜度更優的算法。

為什麼要“重新定義問題,結構化描述”?


把人腦也看做一臺機器的話,很顯然這臺機器的運行方式和效率與計算機有所不同(儘管現在的機器學習在儘可能地模擬人腦的機理,但是兩者至少在現階段還有本質不同)。

人腦在連續信號和非結構化場景下的處理能力是卓越的,但是計算機只能處理離散信號,並且必須最終轉化成結構化數據才能進行處理(儘管現在的機器學習可以通過自我學習來將數據結構化)。

用一張圖來描述這個過程就是:

算法+數據結構(第01篇)走下神壇吧!算法

Why to use Algorithm?(算法有什麼鬼用)


從上面對解決現實問題的過程方法論的描述中,其實已經可以看出算法的價值就在於:經驗的重用。

套用一句IT行話就是“不要重複製造輪子”。好了,既然現在你已經對算法有了大致的感性認識,那麼接下來根據人類的學習習慣,就需要來看看抽象的算法概念,在現實裡到底“長什麼模樣”。

很多人認為“算法=程序或者程序”,這其實是一個狹義的理解。如前面所說的,算法的本質是解決某類問題的方法,而程序或者代碼只是方法的一種表達形式而已。你也可以用自然語言或者偽代碼來進行表達算法。

算法的“模樣”(應對電燈不工作的算法——代碼方式):


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;
}


算法的“模樣”(應對電燈不工作的算法——自然語言方式):


首先檢查電源是否接好了:沒有接好,接上。

如果接上了仍然不工作,看看燈泡是否燒壞了:如果是,換個新燈泡

如果燈泡沒有燒壞,修理燈泡

算法的“模樣”(應對電燈不工作的算法——流程圖方式):

算法+數據結構(第01篇)走下神壇吧!算法


How to use Algorithm?(如何使用算法)


算法的本質就是方法,既然是方法,就是一系列的操作;既然是操作,就必然有作用對象。在軟件程序設計中,這樣的作用對象就是“數據結構”。

怎麼來理解數據結構呢?

前面我們講到了,解決問題的第一步就是要將問題結構化描述。結構化描述的本質就是利用一系列便於操作的“基礎元素”來表達。

那麼怎樣的“基礎元素”是便於操作的呢?

首先我們要清楚,操作的主體是誰。從上一段的闡述來看,這個主體貌似是算法,但是我們注意,算法不是憑空去運行的,是要在計算機上運行的。

所以歸根結底,操作的主體是計算機。所以,這裡所謂的“便於操作”指的是便於計算機運行。

計算機運行有兩個維度:硬件維度和軟件維度。

1.從硬件維度看:

學過計算機組成原理就知道,程序是在計算機的CPU高速緩存和內存中運行的。對應的存儲結構,通常都是線性的。

為了充分提升線性結構的性能優勢,硬件廠商(如CPU廠商)在設計硬件時,就抽象了針對一些結構(如堆棧)的操作(如壓棧、出棧),所以很自然地,這樣的結構就應該作為數據結構。

2.從軟件維度看:

我們編寫的應用程序一般不會直接運行在硬件之上,而是運行在操作系統、運行時或者虛擬機(如JVM)之上。

所以操作系統、運行時或者虛擬機已經抽象的結構(如數組、隊列、樹、圖等),也應該作為數據結構。

上面贅述了這麼多,其實就是要表達一個觀點:算法是要配合數據結構的,拋開數據結構談算法就是無源之水、無根之樹。

看到這裡,我想你一定徹底明白,為什麼圖靈獎得主尼古拉斯·沃斯會提出那個著名的等式了:程序 = 算法 +數據結構。

總結


看到這裡,相信你已經對算法這個概念已經不再陌生,它對於你而言也不再高高在上。

無論在大學學習,還是在工作中,大家都幾乎被一種說法反覆洗腦:算法非常重要,它是計算機的靈魂。

在這裡,我想糾正一下這個錯誤的觀點。首先,廣義的算法不僅僅只是軟件算法;再次,計算機系統不僅僅只是由軟件構成,還有硬件。

硬件涉及到材料科學、製造工藝等一系列技術,這些是不能簡單被算法替代的。所以,脫離上下文、一味強調算法的重要性是耍流氓。

END

博主還有很優秀的技術交流群,很多技術大拿,CTO,活躍度百分八十以上。問題解答百分之90以上。加博主好友後回覆【加群】,然後回答技術問題,答對者才能進入,其他博主和廣告商勿擾進群介紹,當然也會有一些學習資源,群裡直接回復資源介紹即可。


分享到:


相關文章: