演算法,對應的英文單詞是algorithm,這是乙個很古老的概念,最早來自數學領域。
我們都聽過高斯小時的故事和高斯演算法,這裡就不多說了,這是數學領域中演算法的乙個簡單示例。在數學領域裡,演算法是用於解決某一類問題的公式和思想。
而我這裡所講的演算法,是電腦科學領域的演算法,它的本質是一系列程式指令,用於解決特定的運算和邏輯問題。從巨集觀上來看,數學領域的演算法和計算機領域的演算法有很多相通之處。
演算法有簡單的,也有複雜的。
簡單的演算法,諸如給出一組整數,找出其中最大的數。
複雜的演算法,諸如在多種物品裡選擇裝入揹包的物品,使揹包裡的物品總價值最大,或找出從乙個城市到另乙個城市的最短路線。
演算法有高效的,也有拙劣的。
比如高斯的故事中,高斯所用的演算法顯然是更加高效的演算法,它利用等差數列的規律,四兩撥千斤,省時省力地求出了最終結果。
而老師心中所想的演算法,按部就班地乙個數乙個數進行累加,則是一種低效、笨拙的演算法。雖然這種演算法也能得到最終結果,但是其計算過程要低效得多。
在計算機領域,我們同樣會遇到各種高效和拙劣的演算法。衡量演算法好壞的重要標準有兩個。
演算法的應用領域多種多樣
排序演算法是實現諸多複雜程式的基石。
有些演算法可以幫助我們找到最優的決策。
凡是已走上工作崗位的程式設計師,在面試過程中多多少少都經歷過演算法問題的考查,演算法也是大多人的弱項和頭疼的地方。
為什麼面試官那麼喜歡考查演算法呢?
考查演算法問題,一方面可以檢驗程式設計師對計算機底層知識的了解,另一方面也可以衡量一下程式設計師的邏輯思維能力。
資料結構,對應的英文單詞是data structure,是資料的組織、管理和儲存格式,其使用目的是為了高效地訪問和修改資料。
1. 線性結構
線性結構是最簡單的資料結構,包括陣列、鍊錶,以及由它們衍生出來的棧、佇列、雜湊表。
2.樹樹是相對複雜的資料結構,其中比較有代表性的是二叉樹,由它又衍生出了二叉堆之類的資料結構。
3.圖圖是更為複雜的資料結構,因為在圖中會呈現出多對多的關聯關係。
4.其他資料結構
除上述所列的幾種基本資料結構以外,還有一些其他的千奇百怪的資料結構。它們由基本資料結構變形而來,用於解決某些特定問題,如跳表、雜湊鍊錶、點陣圖等。
為了解決時間分析的難題,引入了漸進時間複雜度(asymptotic time complexity)的概念,其官方定義如下:
若存在函式f(n),使得當n趨近於無窮大時,t(n)/f(n)的極限值為不等於零的常數,則稱f(n)是t(n)的同數量級函式。記作t(n)=o(f(n)),稱為o(f(n)),o為演算法的漸進時間複雜度,簡稱為時間複雜度。
因為漸進時間複雜度用大寫o來表示,所以也被稱為大o表示法。
其實就是時間複雜度就是把程式的相對執行時間函式,t(n)簡化為乙個數量級,這個數量級可以是n、n2、n3等。
如何推導出時間複雜度呢?有如下幾個原則。
場景1
t(n) = 3n,
最高端項為3n,省去係數3,則轉化的時間複雜度為:t(n)=o(n)。
場景2
t(n) = 5logn,
最高端項為5logn,省去係數5,則轉化的時間複雜度為:t(n) =o(logn)。
場景3
t(n) = 2,
只有常數量級,則轉化的時間複雜度為:t(n) =o(1)。
場景4
t(n) = 0.5n2+ 0.5n,
最高端項為0.5n2,省去係數0.5,則轉化的時間複雜度為:t(n) =o(n2)。
在時間複雜度相同的情況下,演算法占用的記憶體空間自然是越小越好。如何描述乙個演算法占用的記憶體空間的大小呢?這就用到了演算法的另乙個重要指標——空間複雜度(space complexity)。
空間複雜度是對乙個演算法在執行過程中臨時占用儲存空間大小的量度,它同樣使用了大o表示法。
程式占用空間大小的計算公式記作s(n)=o(f(n)),其中n為問題的規模,f(n)為演算法所佔儲存空間的函式。
1. 常量空間
當演算法的儲存空間大小固定,和輸入規模沒有直接的關係時,空間複雜度記作o(1)。比如下面程式
void fun1(int n)
2. 線性空間
當演算法分配的空間是乙個線性的集合(如陣列),並且集合大小和輸入規模n成正比時,空間複雜度記作o(n)。比如:
void fun2(int n)
3. 二維空間
當演算法分配的空間是乙個二維陣列集合,並且集合的長度和寬度都與輸入規模n成正比時,空間複雜度記作o(n2)。
void fun3(int n)
4. 遞迴空間
遞迴是乙個比較特殊的場景。雖然遞迴**中並沒有顯式地宣告變數或集合, 但是計算機在執行程式時,會專門分配一塊記憶體,用來儲存「方法呼叫棧」。
「方法呼叫棧」包括進棧和出棧兩個行為。 當進入乙個新方法時,執行入棧操作,把呼叫的方法和引數資訊壓入棧中。
當方法返回時,執行出棧操作,把呼叫的方法和引數資訊從棧中彈出。
下面這段程式是乙個標準的遞迴程式:
void fun4(int n) fun4(n-1); ...}
執行遞迴操作所需要的記憶體空間和遞迴的深度成正比。純粹的遞迴操作的空間複雜度也是線性的,如果遞迴的深 度是n,那麼空間複雜度就是o(n)。
人們之所以花大力氣去評估演算法的時間複雜度和空間複雜度,其根本原因是計算機的運算速度和空間資源是有限的。
對於計算機系統來說也是如此。雖然目前計算機的cpu處理速度不斷飆公升,記憶體和硬碟空間也越來越大,但是面對龐大而複雜的資料和業務,我們仍然要精打細算,選擇最有效的利用方式。
但是,正所謂魚和熊掌不可兼得。很多時候,我們不得不在時間複雜度和空間複雜度之間進行取捨。
在絕大多數時候,時間複雜度更為重要一些,我們寧可多分配一些記憶體空間, 也要提公升程式的執行速度。
在計算機領域裡,演算法是一系列程式指令,用於處理特定的運算和邏輯問題。
資料結構是資料的組織、管理和儲存格式,其使用目的是為了高效地訪問和修 改資料。
資料結構包含陣列、鍊錶這樣的線性資料結構,也包含樹、圖這樣的複雜資料 結構。
時間複雜度是對乙個演算法執行時間長短的量度,用大o表示,記作t(n)=o(f(n))。
常見的時間複雜度按照從低到高的順序,包括o(1)、o(logn)、o(n)、 o(nlogn)、o(n2)等。
空間複雜度是對乙個演算法在執行過程中臨時占用儲存空間大小的量度,用大o表示,記作s(n)=o(f(n))。
常見的空間複雜度按照從低到高的順序,包括o(1)、o(n)、o(n2)等。其中遞迴演算法的空間複雜度和遞迴深度成正比。
資料結構時間複雜度 資料結構之時間複雜度分析
正文 開篇我們先思考這麼乙個問題 一台老式的 cpu 的計算機執行 o n 的程式,和一台速度提高的新式 cpu 的計算機運 o n2 的程式。誰的程執行效率高呢?答案是前者優於後者。為什麼呢?我們從時間複雜度分析就可以知道。1 什麼是時間複雜度?在進行演算法分析時,語句總的執行次數 t n 是關於...
資料結構與時間複雜度
什麼是資料結構?資料元素相互之間的關係稱為結構,資料結構是相互之間存在一種或多種特定關係的資料元素的集合。資料結構包括三個方面的內容 邏輯結構,儲存結構,和資料運算。資料的邏輯結構和儲存結構是密不可分的兩個方面。乙個演算法的設計取決於所選定的邏輯結構,而演算法的實現依賴於所採用的儲存結構。資料的邏輯...
資料結構與時間複雜度
資料結構是相互之間存在一種或多種特定關係的資料元素的集合。邏輯結構就是資料之間的關係。而按資料之間的關係來說,大概可以分為兩種 線性結構和非線性結構。非線性結構 什麼是儲存結構?邏輯結構指的是資料間的關係,而儲存結構是邏輯結構的儲存映像。通俗的講,可以將儲存結構理解為邏輯結構用計算機語言的實現。常見...