學習數據結構和算法。咱們要知道一些基礎的知識。算法
算法(英文algorithm
)這個詞在中文裏面博大精深,表示算帳的方法,也能夠表示指揮若定的計謀等。在計算機科技裏,它表示什麼呢?編程
計算機,顧名思義是用來計算的機器。算法在計算機科學中能夠描述爲:計算機接收一個輸入指令,而後進行一個過程處理,最後輸出計算的結果。segmentfault
這種輸入-過程處理-輸出,用人類的行爲模式,很容易理解,好比媽媽讓小明去打醬油,打醬油的命令是輸入,小明發現小區周邊有5家店有醬油出售,娟娟超市是離家最近的,而子龍雜貨店雖然離得最遠,但醬油很便宜。小明爲了省錢,跑到最遠的子龍雜貨店買了醬油,而後順利回到了家,交給了媽媽。買醬油的過程就是處理,而給媽媽的醬油是輸出。小明爲何不去最近的娟娟超市,而去了最遠的子龍雜貨店,這是小明腦殼裏思考後產生的最佳方案。固然,如今買醬油能夠經過外賣軟件,小明能夠打開美團外賣軟件,搜索關鍵字:醬油,而後點擊篩選,離家最近的和最便宜的,而後選擇最便宜的醬油下單。數組
買醬油的過程 = 美團外賣軟件下單的過程。數據結構
人類在幾千年的演化中,會進行數字運算了,會進行利益權衡了,而後造了機器,將本身的行爲模式,賦予了機器,解放了自身。若是人類真正瞭解人腦神經元的信息傳遞過程,甚至可能造出有自我意識的機器,但這種場景仍然只能在科幻電影中看到。併發
因此,這個邏輯過程,或行爲模式,在計算機裏面映射的是算法。機器學習
用更準確的描述來講:算法是一種有限,肯定,有效
的並適合用計算機程序來實現的,用來解決問題的方法。首先,有一個問題,而後有一個方法去解決它,這個方法叫算法。數據結構和算法
算法是有限的,就是算法的步驟是有限的,執行的時間也是有限的,可以在有限時間內得出結果。算法是肯定的,就是不管執行多少次,計算得出的結果都同樣。算法是有效的,就是計算出的結果對解決問題有幫助。編程語言
然而算法的定義一直被刷新,由於機器學習的出現,基於海量超大規模數據,機器學習算法的步驟是無限的,能夠一直計算下去,每次計算的結果也不同,但若是人爲進行步驟限制,以及增長訓練閾值,訓練時得出的參數超過設定的閾值立刻中止運算,倒也符合以上的定義。函數
算法要在有限的時間內完成,自己是對人類的一種負擔,由於人類造出的機器還不夠強。爲何呢?由於即便算法的步驟是有限的,執行的時間也可能特別長。
正如《從一到無窮大》書中印度教聖地貝拿勒斯神廟下的三根寶石針,印度教主神焚天說過,誰能夠把第一根寶石針的64塊金片經過第二根寶石針移到第三根,焚天塔,神廟,婆羅門將化爲灰燼,這是有名的漢諾塔算法。
漢諾塔問題能夠描述爲:
有三根杆(編號A、B、C
),在A
杆自下而上、由大到小按順序放置64
個金盤(以下圖)。遊戲的目標:把A
杆上的金盤所有移到C
杆上,並仍保持原有順序疊好。
操做規則:每次只能移動一個盤子,而且在移動過程當中三根杆上都始終保持大盤在下,小盤在上,操做過程當中盤子能夠置於A、B、C
任一杆上。
咱們很天然想到一個算法:
C
杆,將A
杆前面N-1
個盤子,移動到B
杆後,將A
杆剩下的一個盤子,直接移動到C
杆,這時候A
空了。A
杆,將B
杆的N-1
個盤子,移動到C
杆,任務就完成了。十分樸素的思路,咱們用編程語言來實現:
package main import "fmt" var total = 0 // 漢諾塔 // 一開始A杆上有N個盤子,B和C杆都沒有盤子。 func main() { n := 4 // 64 個盤子 a := "a" // 杆子A b := "b" // 杆子B c := "c" // 杆子C tower(n, a, b, c) // 當 n=1 時,移動次數爲 1 // 當 n=2 時,移動次數爲 3 // 當 n=3 時,移動次數爲 7 // 當 n=4 時,移動次數爲 15 fmt.Println(total) } // 表示將N個盤子,從 a 杆,藉助 b 杆移到 c 杆 func tower(n int, a, b, c string) { if n == 1 { total = total + 1 fmt.Println(a, "->", c) return } tower(n-1, a, c, b) total = total + 1 fmt.Println(a, "->", c) tower(n-1, b, a, c) }
經過概括,咱們能夠知道移動次數Total(N)
的關係是Total(N)=2*Total(N-1)+1
,每多一個盤子,移動次數就會翻倍加一,咱們經過相關的數列數學方法能夠知道Total(N)=2^N-1
,也就是移動次數是一個指數方程:2的N次方
,指數等於盤子的數量。
咱們計算出2^64-1=18446744073709551615
,能夠知道一我的日夜不停,一秒移動一次:18446744073709551615/3600/24/365/100000000=5849
,要5849億年時間才能夠完成這件事,那時候世界確實可能已經毀滅。
在計算機科學中,由於全部的算法都是人定義的規則,規則是死的,因此不要擔憂學不會。當你學會了這些算法,你將會以爲,哇,一切都那麼簡單。
數據結構,顧名思義就是存放數據的結構,也能夠認爲是存放數據的容器。好比,你要找出1000個數字中的最大值,首先你要將1000個數字記在某些卡片上,而後對卡片進行排序。
大多數算法都須要組織數據,因此產生了數據結構。數據結構在計算機中,主要是用來實現各類算法的基礎,固然數據結構自己也是算法的一部分。
基本的數據結構有:鏈表,棧和隊列,樹和圖。
鏈表,就是把數據連接起來,關聯起來,一個數據節點指向另一個數據節點,像天然界的一條條鐵鏈,大部分數據結構,都是由鏈表的若干變種來表示。在每種編程語言中,數組做爲基本數據類型提供,數組是連續的內存存儲空間,經過下標0,1,2能夠迅速獲取到數組指定位置的數據。鏈表也能夠用數組來實現,但通常狀況下,由於數組是連續的,在鏈表增長和刪除節點時容易形成冗餘,效果不佳。因此鏈表在不一樣編程語言實現是這樣的:
C、C++
是用指針來實現的,Java
是用類來實現的,而Golang
是用結構體引用來實現。棧和隊列,主要用來存儲多個數據,只不過一個是先進後出,一個先進先出。好比下壓棧,先入棧的數據是最後才能出來,而咱們熟知的隊列,先排隊的人確定先得到服務。
其次是樹和圖,樹就是有一個樹根節點,存放着數據,下面有不少子節點,也存放着數據,類比天然界的樹。圖則能夠類比天然界的地圖,多個點指向多個點,點和點之間有一條或多條邊,而這些點存放着數據,邊也能夠存放着數據,好比距離等。
圍繞這幾種數據結構,有若干延伸,加上一些排序,查找邏輯,就造成了更高層次的高級數據結構。
數據結構是算法實現的輔助,是爲了更高效組織數據的結構,因此數據結構和算法其實密切聯繫,並不須要分得太清,你們能夠把數據結構等同於算法。
學習算法的緣由,是好的算法能夠節約資源,可是選擇合適的算法很難。咱們要進行復雜的數學分析才能知道,什麼叫作好的,在計算機裏,咱們把這種數學分析這叫作算法分析。
什麼是好的數據結構和好的算法?
計算機資源是有限
的,因此佔用計算機資源越少的數據結構和算法越好。人的生命是有限的
的,等待時間是有忍耐度的,因此能輔助程序越快完成工做的數據結構和算法越好。因此出了個理論:時間和空間算法複雜度理論。
程序執行過程當中,要麼空間換時間,要麼時間換空間,空間能夠認爲是一種計算機資源如內存使用狀況,而時間是人類感知的第四個維度,就是慢仍是快,二者通常不能兼得,若是發現竟然兼得了,那就是發明了一種更好的算法。
在計算機科學發展的四五十年,這種既省資源又省時間的發明仍是比較少的,好比數據壓縮算法,由於發明了超高效的無損數據壓縮算法,咱們網上看視頻的時候,既不失真,也不卡頓,又快又好,這種就叫好算法。
目前有一種新型的計算方式正在研究中,叫量子計算,能夠在很是小的空間,使用很是少的資源,短期內計算超級大量的數據,讓咱們期待能成功量產的那天,到了那時候,人類生產力將極大被解放。
程序設計在通常程度上,不少人都認爲=數據結構+算法。
咱們學習數據結構和算法,是爲了更高效率寫出更快,更好的代碼。
由於學習過,因此咱們不須要從零開始設計,工做效率就提升了。
由於知道每種數據結構和算法的複雜度和適用場景,自由選擇組合,咱們寫出的代碼計算速度變快了,佔用的資源更少了。
因此咱們要好好學習和理解常見的數據結構和算法。
歡迎閱讀剩下的章節。
我是陳星星,歡迎閱讀我親自寫的 數據結構和算法(Golang實現),文章首發於 閱讀更友好的GitBook。