學習資料結構與演算法的時候,避不開的乙個知識點就是:時間複雜度和空間複雜度分析.
為什麼需要複雜度分析?
一段**我寫好了,直接上手跑一遍,不就知道演算法執行的時間和占用的記憶體大小了,為什麼還要做分析呢?而且直接跑一遍得到的資料,準確的不能再準確了.
因為直接跑一遍得到演算法執行的時間和占用的記憶體大小,有一定的侷限性.
第一,同樣一段**,把它拿到 90 年代的筆記本上面執行,和拿到現在的筆記本上面執行,得到的時間是不一樣的,所以直接拿來執行的**,它的準確度真的夠準確嘛?
第二,如果資料量不夠多,直接執行程式得到的結果可能有失其準確性.比如,對於小規模的資料排序,插入排序可能會比快速排序更快.
對於計算時間和空間複雜度,一般是採用大 o 表示法來表示.
時間複雜度計算:
什麼是時間複雜度呢?是指執行當前演算法所消耗的時間.
常見的幾種時間複雜度:o(1),o(log
2nlo
g2n
),o(n),o(n2n
2),o(2n2
n),o(n!)
先來看一段簡單的**:
int n=
1000
;system.out.
println
("hi, your input is:"
+n);
system.out.
println
("hey, your code is:"
+n);
system.out.
println
("hello, your verification code is:"
+n);
先別往下看,你覺得這段**的時間複雜度是多少?
是 o(1) 對吧?因為這段**都是常量級的執行時間,所以對於時間複雜度來說,它的複雜度為 o(1).
請注意: o(1) 並不是指執行了一行**,上面的程式執行了 3 行**,它的時間複雜度也是 o(1).只要**的執行時間不隨 n 的增大而增長,那時間複雜度就都記為 o(1).一般情況下,只要程式中不存在迴圈語句,遞迴語句,就算是有上萬行的**,時間複雜度也是 o(1).
來看另外一段**:
for
(int i=
1;i<=n;i++
)
你覺得這段**的時間複雜度是多少?
先來分析一下,這段**執行了 n 次, 所以它的時間複雜度為 o(n).
如果是這樣呢:
for
(int i=
1;i<=n;i++
)}
這段**的時間複雜度是多少呢?
首先它有兩個 for 迴圈,每個迴圈都會走 n 遍,所以這段**的時間複雜度為 o(n2n
2) .
如果將以上**合併在一起,它們的複雜度是多少?是 o(1) + o(n) + o(n2n
2) 嘛?
不,只是 o(n2n
2) .因為當 n 足夠大時, o(1) 和 o(n) 對於程式的影響幾乎都可以忽略不計,此時我們只需要關注最大量級即可.
接下來說說,空間複雜度計算:
什麼是空間複雜度呢?是指執行當前演算法需要占用的記憶體空間大小.也就是看使用了幾個輔助變數.
照樣上幾段**來看看.
void
fun(
int n)
對於這段**來說,它的空間複雜度是多少?
應該比較容易看出來,只使用了乙個輔助變數,所以它的空間複雜度為 o(1).
void
fun(
int n)
這段**,申請了乙個大小為 n 的陣列,所以它是申請了 n 個輔助變數,所以它的空間複雜度為 o(n).這段**是申請了一維的,如果是這樣呢:
void
fun(
int n)
你一定猜到了,它的空間複雜度是 o(n2n
2)
資料結構與演算法(03)
1.雙鏈表應用例項 1.1雙向鍊錶的操作分析和實現 使用帶head頭的雙向鍊錶實現 管理單向鍊錶的缺點分析 1 單向鍊錶,查詢的方向只能是乙個方向,而雙向鍊錶可以向前或者向後查詢。2 單向鍊錶不能自我刪除,需要靠輔助節點,而雙向鍊錶可以自我刪除,單鏈表刪除時節點,總是找到temp,temp是刪除節點...
資料結構 演算法 03
1.棧結構實現 棧可以用順序表實現,也可以用鍊錶實現。棧的操作 stack 建立乙個新的空棧 push item 新增乙個新的元素item到棧頂 pop 彈出棧頂元素 peek 返回棧頂元素 is empty 判斷棧是否為空 size 返回棧的元素個數 2.佇列 佇列 queue 是只允許在一端進行...
資料結構與演算法03 單鏈表
使用帶頭節點的單向鍊錶,實現水滸英雄排行榜的管理。對英雄人物完成增刪改查等操作。package com.wang.linkedlist author wzy create 2020 02 03 12 35 public class linkedlist 定義singlelinkedlist clas...