、## 如何分析、統計演算法的執行效率和資源消耗
.複雜度描述的是演算法執行時間(或占用空間)與資料規模的增長關係。為什麼要需要複雜度分析?
測試結果非常依賴測試環境,而且受資料規模影響很大,所以需要乙個不用具體資料來測試,可以粗略估計演算法的執行效率的方法
如何在不執行**的情況下,粗略的估算一段**的執行時間
int
cal(
int n)
return sum;
}
因為是粗略估計**的執行時間,所以可以假設每行**執行的時間都一樣,為unit_time。在這個假設的基礎上,估算這段**的執行時間。
可以看出第2、3行**分別需要1個unit_time的時間,第4、5行**都執行了n次,所以需要2nunit_time的時間,所以這段**總的執行時間就是(2n+2) unit_time。
int
cal(
int n)
}}
這段**的總執行時間t(n) = (2n² + 2n + 3) * unit_time
可以看出所有**的執行時間與每行**的執行次數n成正比。這個規律總結成乙個公式。
t(n) = o (f(n))t(n)表示**執行的時間,n表示資料規模的大小,f(n)表示每行**執行次數的總和,公式中的 o 表示**的執行時間t(n) 御f(n)表示式成正比。
大 o 時間複雜度實際上並不具體表示**的真正執行時間,而是表示**執行時間隨資料規模增長的變化趨勢, 所以也叫做漸進時間複雜度,簡稱時間複雜度。
當資料規模 n 很大時,公式中的低階、常量、係數三部分並不左右增長趨勢,所以都可以忽略。所以只需要記錄乙個最大量級就可以了,如果用大 o 表示法表示上邊兩段**的時間複雜度, 就可以記為: t(n)=o(n); t(n)=o(n²)。
如何分析一段**的時間複雜度
1.只關注迴圈次數最多的一段**
比如前邊的第一段**中,只需要關注執行次數最多的第4、5行**,所以總的時間複雜度就是o(n)。
2.加法法則:總複雜度等於量級最大的那段**的複雜度
int
cal(
int n)
int sum_2 =0;
int q =1;
for(
; q < n;
++q)
int sum_3 =0;
int i =1;
int j =1;
for(
; i <= n;
++i)
}return sum_1 + sum_2 + sum_3;
}
這段**分為三部分,分別為sum_1、sum_2、 sum_3。我們可以分析每一部分的時間複雜度,然後把他們放到一起,再取乙個量級最大的作為整段**的複雜度。
第一部分的時間複雜度,這段**執行了100次,所以是乙個常量的執行時間,和n的規模無關。即便這段**執行了1000000次,只要是乙個已知數,當n無限大時,就可以忽略,儘管對**的執行時間會有很大影響,但是回到時間複雜度的概念來說,不管常量的執行時間多大,我們都可以忽略掉。因為它本身對增長趨勢並沒有影響。
如果t1(n)=o(f(n)),t2=o(g(n)),t3=o(h(n)),那麼t(n) = t1(n)+t2(n)+t3(n)=max(o(f(n)),o(g(n)),o(h(n)))=o(max(f(n),g(n),h(n))。
3.乘法法則:巢狀**的複雜度等於巢狀內外**複雜度的乘積
如果 t1(n)=o(f(n)),t2(n)=o(g(n));那麼 t(n)=t1(n)*t2(n)=o(f(n))*o(g(n))=o(f(n)*g(n)).
幾種常見時間複雜度
非多項式量級:o(2ⁿ)和 o(n!),當資料規模n越來越大時,非多項式量級演算法的執行時間會急劇增加,執行時間會無限增長,所以,非多項式時間複雜度的演算法其實是非常低效的演算法。因此,我們主要看幾種常見的多項式時間複雜度。
首先,你必須明確乙個概念,o(1)只是常量級時間複雜度的一種表示方法,並不是指只執行了一行**。所以,只要**的執行時間不隨n的增大而增長,這樣**的時間複雜度我們都記做o(1)。或者說,一般情況下,只要演算法中不存在迴圈語句、遞迴語句、不論有多少行的**,其時間複雜度也是 o(1)。
對數階時間複雜度非常常見,同時也是最難分析的一種時間複雜度。我們通過乙個例子來說明 。
i=1;
while
(i <= n)
從**中可以看出,i的取值從1開始,每次都乘以2,是乙個等比數列,當i大於n時,迴圈結束。
所以只需要通過2^x=n 求解 x 這個問題我們想高中應該就學過了,我就不多說了。x=log₂n。所以這段**的時間複雜度就是o(log₂n)。
實際上,不管是以2為底,以3為底,還是以10為底,所有的對數階的時間複雜度都記為o(logn)。為什麼呢?
**的時間複雜度由兩段**決定,我們無法評估兩個資料規模誰的量級更大,所以我們在表示複雜度的時候,就不能簡單的利用加法法則,省略掉其中乙個。所以,時間複雜度應該為o(m+n)。
針對這種情況,原來的加法法則改為:t1(m)+t2(n) = o(f(m)+g(n))。但是乘法法則繼續有效:t1(m)*t2(n) = o(f(m)+f(n))。
空間複雜度表示演算法的儲存空間與資料規模之間的增長關係
我們常見的空間複雜度就是o(1)、o(n)、o(n²)
小結
可以粗略的表示。越高階複雜的演算法,執行效率越低。常見的複雜度並不多,從低階到高階有:o(1)、o(logn)、o(n)、o(n²)。
抄課代表筆記
總結一、什麼是複雜度分析?
1.資料結構和演算法解決是「如何讓計算機更快時間、更省空間的解決問題」。
2.因此需從執行時間和占用空間兩個維度來評估資料結構和演算法的效能。
3.分別用時間複雜度和空間複雜度兩個概念來描述效能問題,二者統稱為複雜度。
4.複雜度描述的是演算法執行時間(或占用空間)與資料規模的增長關係。
二、為什麼要進行複雜度分析?
1.和效能測試相比,複雜度分析有不依賴執行環境、成本低、效率高、易操作、指導性強的特點。
2.掌握複雜度分析,將能編寫出效能更優的**,有利於降低系統開發和維護成本。
三、如何進行複雜度分析?
1.大o表示法
1)**
演算法的執行時間與每行**的執行次數成正比,用t(n) = o(f(n))表示,其中t(n)表示演算法執行總時間,f(n)表示每行**執行總次數,而n往往表示資料的規模。
2)特點
以時間複雜度為例,由於時間複雜度描述的是演算法執行時間與資料規模的增長變化趨勢,所以常量階、低階以及係數實際上對這種增長趨勢不產決定性影響,所以在做時間複雜度分析時忽略這些項。
2.複雜度分析法則
1)單段**看高頻:比如迴圈。
2)多段**取最大:比如一段**中有單迴圈和多重迴圈,那麼取多重迴圈的複雜度。
3)巢狀**求乘積:比如遞迴、多重迴圈等
4)多個規模求加法:比如方法有兩個引數控制兩個迴圈的次數,那麼這時就取二者複雜度相加。
四、常用的複雜度級別?
多項式階:隨著資料規模的增長,演算法的執行時間和空間占用,按照多項式的比例增長。包括,
o(1)(常數階)、o(logn)(對數階)、o(n)(線性階)、o(nlogn)(線性對數階)、o(n2)(平方階)、o(n3)(立方階)
非多項式階:隨著資料規模的增長,演算法的執行時間和空間占用暴增,這類演算法效能極差。包括,
o(2^n)(指數階)、o(n!)(階乘階)
五、如何掌握好複雜度分析方法?
複雜度分析關鍵在於多練,所謂孰能生巧。
資料結構與演算法之美 複雜度分析
因為我們需要乙個不用具體的測試資料來測試,就可以粗略估計演算法的執行效率的方法。演算法的執行效率,粗略地講,就是演算法 執行的時間。舉個例子 int cal int n 首先,所有 的執行時間 t n 與每行 的執行次數成正比。我們依舊假設每個語句的執行時間是 unit time。那這段 的總執行時...
資料結構與演算法 02 複雜度分析
資料結構與演算法的本身解決的是 快 和 省 的問題。節省空間,且執行效率快,今天我們通過複雜度分析來考量 的執行效率,複雜度又分為時間複雜度和空間複雜度兩大類。事後統計法 通過運用工具監控的 執行的方法,統計 的執行時間和占用空間。這種方法無法真實的反應 的效能。1.1 測試結果非常依賴測試環境 受...
資料結構與演算法之美(二) 複雜度分析
資料結構和演算法解決的問題是 如何讓計算機更快時間 更省空間地工作 更快 更省的效能需要有東西來衡量,複雜度分析就是分別從執行時間和占用空間兩個維度來評估資料結構和演算法的效能 分別用時間複雜度和空間複雜度兩個概念來描述效能問題,二者統稱為複雜度。複雜度描述的是演算法執行時間 或占用空間 與資料規模...