Programs, after all, are concrete formulations of abstract algorithms based on particular representations and structures of data. — Niklaus Wirth
已故Pascal的開發者Niklaus Wirth曾着有一書,名叫《Algorithms + Data Structures = Programs》,
意指一切程式都是由演算法和數據結構組成,只要了解演算法和數據結構,你便能了解一切的電腦程式。
既然演算法和數據結構如此重要,那什麼是演算法,什麼又是數據結構?
什麼是演算法 ?
演算法這詞在最近十年被自媒體圈濫用的相當嚴重,彷彿隨便瞎扯幾次演算法,就能開多幾個自媒體課程一般。
然而實際上演算法這詞和社交媒體平台還真的沒什麼直接關係。
首先,要認識到的關鍵一點是,「演算法」這三個字是個很不精準的翻譯,「演算法」聽起來就像是一種可以被實施的方法,就像是加法,乘法一樣是去抽象化的一種實際行為。但事實卻並非如此,和「演算法」這三個字的語感所表述的相反,Algorithms是一個特別抽象化的名詞 ( 如果不了解什是抽象化,推薦看一下以前關於抽象化的文章 ) 。
在日文裡的Algorithms有兩種叫法,一是「アルゴリズム」,即用片假名寫出的發音,二是「演算手順」。
實在無法否認的是,無論是哪一種叫法,都比中文裡「演算法」這三個字來得容易理解。
因此,在這裡我們以「演算手順」這翻譯來簡單闡釋什麼是Algorithms。
「演算手順」,非常容易理解,四個字分成兩個部分,一是「演算」可以理解成計算,二是「手順」可以理解成工序。
所以「演算手順」簡單而言就是「計算的工序/步驟」。聽起來非常簡單對吧,既沒有專業名詞,也不需要複雜的定義。
能如此簡單的解釋的原因在於Algorithms本來就不是什麼遠在天邊的詞,Algorithms詞源來自八世紀阿拉伯數學家穆罕默德·花拉子密(Muhammad al-Khwarizmi)的名字 al-Khwarizmi 演變而來。在八世紀末,花拉子密提出了不少的計算方法以解決了各種數學問題,例如一元一次方程、一元二次方程以及各種天文學問題。而在花拉子密死後,他提出的一系列計算方法就被簡稱為「花拉子密的算法 (al-Khwarizmi’s)」。隨着時代過去,詞彙則逐漸演化成「Algorithms」。所以Algorithms一點都並不複雜,就只是單純的「計算的工序」罷了。例如像是2x = 5,至少讀過初中的人都知道找出x的方法就是把左值和右值都除以2,最後變成 2x /2 = 5 /2、x = 2.5,而這個過程就是一個Algorithms。
什麼是數據結構 ?
好玩的是,數據結構這詞和演算法一樣,絕對都可以被列進「十大被濫用詞彙大賞」,各路假IT大師都是一口一個數據結構。
但數據結構和演算法之間有一個比較大的差異,那便是演算法聽起來很抽象,但實際上很具體。而數據結構聽起來很具體,但實際上卻特別抽象。
數據結構故名思意是指「擺放數據的方式」,但在正式的電腦科學領域所使用的數據結構並不只是單純擺放數據的方式。更關鍵的一環在於其目的,「為了特定計算的目的而設計的數據擺放方式」。就如同演算法,「計算的工序」是為其計算的目標而存在,並為計算目標而服務,而一個「數據結構」也是為了特定計算目標存在並服務的。只不過一般各路假IT大師提起數據結構時,卻忽視了「為了特定計算目標存在並服務」這一個核心概念,只要是和數據有關的都通通叫都數據結構,一個SQL表的格式又叫數據結構,隨便一個Excel也可以叫數據結構,每次聽到同事亂講數據結構這個詞,我腦袋就開始痛了,雖然抽象化的詞彙本來就是複合的,但SQL表和Excel實在是遠超出數據結構的特徵範圍了。
如果要更好理解數據結構,可以先釐清一下「數據結構」、「數據容器」和「數據儲存設備」的關係,
數據儲存設備,例如記憶體/硬碟是具體的數據儲存空間,通常會被以一格一格的形式被理解,每一格就是一個字節,八個位元,這一部分應該很好理解。
而數據容器是對比數據儲存空間更抽象化的一種儲存格式,在具體實施的層面上,數據容器通常會隨語言有不同的細節上的差異,例如C++的map和C#的Dictionary都是非常類似的數據容器,但因為不同的程式語言有不同的實現,因此兩者在使用上會有些許微差異,所以數據容器 ≈ 在程式設計上抽象化的數據儲存空間。
數據結構是則最為抽象化的數據儲存方式,由於它高度抽象化的屬性,使數據結構並非具體存在的物件,通常只會是以一種概念性的「方法論」而存在,用來指導如何進行數據容器的設計,例如C++的map是一種數據容器,而map所利用的數據結構是binary-tree,map是一個在程式碼可以被使用的「容器」,但binary-tree則只是一個「概念」或「容器的設計藍圖」。而C++的map和C#的Dictionary都是以binary-tree概念開發的,但map和Dictionary是數據容器,而binary-tree才是數據結構。
因此,數據結構可以理解成流體力學的理論,而數據容器則是基於流體力學的理論蓋成的船,
而這艘船會在名為數據儲存設備的海洋上行駛。
演算法加數據結構等於程式
看到這裡應該已經了解為什麼演算法和數據結構總是一起被談起,因為演算法和數據結構都是為了「完成計算」而存在的,開發者設計好一個數據結構,並在這個數據結構上再設計一個演算法,其最終的成品就是程式 ( Programme )。寫一個電子遊戲本質上就是一堆又一堆的計算,例如如何渲染畫面是計算出來的、物件如何碰撞也是計算出來的,寫一個行動裝置應用都是一堆又一堆的計算要處理,而要進行計算就必然要有用來計算的演算法和用來決定數據如何擺放的數據結構,這也是為什麼Niklaus Wirth會說「Algorithms + Data Structures = Programs」。
而如何使用演算法和數據結構來計算,以在程式開發上在更好的效能,便是這一系列文章的內容。
核心摘要 ( Takeaway )
演算法 ( Algorithms ) : 為了特定計算的目的而設計的計算工序/步驟。
數據結構 ( Data Structures) : 為了特定計算的目的而設計的數據擺放方式。
演算法和數據結構的關係 : 開發者設計數據結構,並在這個數據結構上再設計演算法,便是程式。
發佈留言