我們會使用數學分析為演算法成本建立簡潔模型並使用實驗資料驗證這些模型。
(一)第乙個挑戰是:決定如何定量測量程式的執行時間?
一般來說,數學模型中的對數項是不能忽略的,但在倍率假設中它在**效能的公式中的作用並不那麼重要。
對於編寫的每個程式,你都需要能夠回答這個基本問題:「該程式能在可接受的時間內處理這些資料嗎?」
我們會按照以下方式解決問題:
1. 實現並分析該問題的一種簡單的解法。我們通常將它們稱為暴力演算法。如threesum
2. 考查演算法的各種改進,它們通常都能降低演算法所需的執行時間的增長數量級。如threesumfast。
3. 用實驗證明新的演算法更快。
(二)在對程式的效能進行仔細分析的時候,可能得到不一樣的結果。它們是由於我們的猜想基於的乙個多多個假設並不完全正確所造成的。
我們需要注意的事項有:
1. 大常數
在首項近似中,我們一般會忽略低階項中的常數係數,但這可能是錯的。例如2n2+cn。因此,我們要對可能的大常數儲存敏感。
2. 非決定性的內迴圈
內迴圈是決定性因素的假設並不總是正確的。錯誤的成本模型可能無法得到真正的內迴圈。
3. 指令時間
每條指令執行所需的時間總是相同的假設是不正確的。
例如說:大多數現代計算機系統都會使用快取技術來組織記憶體,在這種情況下訪問大陣列中的若干個並不相鄰的元素需要的時間可能很長。
4. 系統因素
例如有好幾個程式正在執行。
5. 不分伯仲
常常出現的一種情況是:其中在某些場景中更快,而在另一些場景中更慢。有些程式設計師特別喜歡投入大量的精力進行比賽並找出「最佳」實現,但此類工作最好還是留給專家。
6. 對輸入的強烈依賴
以threesum為例,如果我們的問題是「輸入中是否存在和為0的三個整數」,修改threesum病返回bool值,那麼如果輸入中的頭三個整數的和為0,該程式的執行時間的增長數量級為常數級別;如果不含有這樣的三個整數,程式的執行時間的增長數量級為立方級別。
乙個重要的問題是對於輸入的依賴。如何處理這一問題?
方法一:對最壞情況下的效能的保證
子計算機系統中最壞情況是非常現實的憂慮,因為程式的輸入可能來自另外乙個使用者而非自然界。
方法二:隨機化演算法
為效能提供保證的一種重要方法是引入隨機性。例如,快速排序在最壞情況下的效能是平方級的,但是通過隨機打亂輸入,根據概率我們可以保證它的效能是線性對數的。雜湊演算法在最壞情況下的效能是線性級別的,但是根據概率我們可以保證它的執行時間是常數級別的。
方法三:均攤分析
這裡針對的問題是:操作序列可能導致效能不同。
我們的解決辦法是:記錄所有操作的總成本並除以操作總數來將成本均攤。
(三 總結)
速度極慢的程式和不正確的程式一樣無用。
在程式設計領域中,最常見的錯誤或許就是過於關注程式的效能。首要任務是應該是寫出清晰正確的**。僅僅為了提高執行速度而修改程式的事最好留給專家們來做。事實上,這麼做常常會降低生產效率,因為它會產生複雜而難以理解的**。所謂「在程式設計領域,不成熟的優化是所有的罪惡之源」。
第二個常見錯誤或許是完全忽略程式的效能。
幾個重要的圖表
(1.5部分)
為了說明我們設計和分析演算法的基本方法,我們現在來學習乙個具體的例子,我們的目的是強調以下幾點:
優秀的演算法因為能夠解決實際問題而編的更為重要;
高效演算法的**也可以很簡單
理解某個實現的效能特點是一項有趣而令人滿足的挑戰;
在解決同一問題的多種演算法之間進行選擇時,科學方法是一種重要的工具;
迭代式改進能夠讓演算法的效率越來越高。
我們再次強調:
完整而詳細地定義問題,找出解決問題所必須的基本抽象操作並定義乙份api;
簡潔地實現一種初級演算法,給出乙個精心組織的開發用例並使用實際資料作為輸入;
當實現所能解決的問題的最大規模達不到期望時決定改機還是放棄;
逐步改進實現,通過經驗性分析或(和)數學分析驗證改進後的效果;
用更高層次的抽象表示資料結構或演算法來設計更高階的改進版本;
如果可能盡量為最壞情況下的效能提供保證,但在處理普通資料時也要有良好的效能;
在適當的時候將更細緻的深入研究留給有經驗的研究者並繼續解決下乙個問題。
演算法第四版1 4演算法分析 習題1 4 31
組成 headstack,tailstack,tempstack headstack的棧底為佇列的頭,棧頂與tailstack的棧底相連,tailstack的棧頂為佇列的尾。pushleft 放在headstack的最底部。若headstack為空,直接入棧,若不為空,全部倒入tempstack,入...
《演算法(第四版)》排序 模板
本書對排序類演算法有乙個模板,包括了以下幾種方法 1 sort 這個方法裡面實現的就是排序的演算法 2 less 這個方法裡是利用了comparable介面裡的compareto方法,其中compareto方法對於本物件與傳入的比較物件小於,等於,大於,分別返回負數,0,正數 這個方法如果compa...
演算法 第四版 練習1 4 2
修改threesum,正確處理兩個較大的int值相加可能溢位的情況 首先jdk中定義int佔4個位元組,32位 後面全部的計算都是以此為根據的 32位就是jvm僅僅給分配32個格仔的空間,用以存放資料。總所周知計算機中用0和1存放資料。那麼,32個格仔中放滿0或1的方法 有2的32次方種 或者說32...