資料結構與算法系列(一):時間複雜度和空間複雜度
本篇開始,梳理總結資料結構與演算法。雖然開的系列都比較多,可是都很重要。
資料結構和演算法是區分程式員和碼農的標誌之一,當然我認為軟體工程師比程式設計師更高階一些哈。
系列中每篇都是消化吸收以後再整理的,以此來標識自己這部分已經理解了。 咳咳咳,我們學習他們的目的也只是為了應用,像是什麼資料推理證明之類的,呃,脫離場景都是耍流氓,我又不做演算法方向,花這麼大經歷去研究證明過程之類的,mdzz嗎?所以以後文章都是偏應用方向。
推薦書單
不負責推薦一波,當然都是廣受好評的。只看過《演算法》。
可能配合著看更好吧
入門:《大話資料結構》,《演算法圖解》
系統學習:《資料結構與演算法描述》
大部頭:《演算法(第4版)》
基礎
如果說資料結構和演算法是程式設計的基礎之一的話,那麼接下來幾個概念就是資料結構與演算法的通用基礎:
- 時間複雜度
- 空間複雜度
而他倆的理論基礎又是:
- 大O表示法
- 幾個小小數學方面的
OK,一個個來。
基礎的基礎
大O表示法
先來看兩個函式的座標影象,他們是:
座標圖為:

可以看到,黃色曲線的增長趨勢遠遠大於藍色曲線的增長趨勢。此時,n才取值30,如果
那麼二者的差異將會非常非常大。 在演算法領域中,這個增長趨勢我們就用 大O表示法
表示。 所以
就表示 縱座標y的值
隨 橫座標n
的增長趨勢,該增長趨勢就是
這個函式的影象。 說完了,關於 y軸
具體指代什麼,稍後再說。
幾個數學方面的
上文說的大O表示法,我們可以在
的情境下去看。 比如
,當處於 式1
的情況下,由於 大O表示法 表達的是 y軸數值的增長趨勢。假如 n 分別等於 1,1億,很明顯,起決定作用的是:
很明顯,是
。 所以
。說這個的意思呢,就是說盡管 式2
是一個多項式,但是在大O分析法的場景下,我們只看對於增長趨勢影響最大的項。 證明也很好證明:增長趨勢顧名思義就是增長比例麼,也就相當於是 y / x
。 式子2除以 n以後就變成了:
,可以進一步簡化成, 所以對於增長趨勢影響最大的就是第一項,
。
常見的函式影象
在演算法領域中,總共就幾種需要掌握的函式影象,如下圖:

在大O表示法下,他們表示的都是增長趨勢,大家可以除以n後自行證明哪個大哈,看圖也一樣。 結論:
時間與空間複雜度
評價演算法效能就是看 執行時間 和 儲存空間 佔用的。為什麼是這兩個引數呢? 我認為應該是這樣子的:結合馮諾依曼體系結構來看,計算機由:儲存器,計算器,控制器和輸入輸出裝置組成。而輸入輸出裝置和控制器無需考慮,所以就剩下儲存器和計算器了。演算法在單臺機器上來說不就是要減少計算和儲存嗎?愚見。
嗯,所以就引出了 時間複雜度
和 空間複雜度
的概念。
時間複雜度
上文的大O表示法中,y軸的座標值一直沒有具體定義。我們假設機器執行每條指令的時間都是一樣,比如是1個時間單位,所以就相當於執行c條指令花費的時間單位就是c。 在分析演算法的時間複雜度時,我們把大O表示法的縱座標軸表示為 程式執行花費的時間(或者說指令執行的次數),所以: 時間複雜度O(n)就表示為:程式正確執行完畢花費時間的增長趨勢。而具體
則是看括號中的函式,也就是上文中的圖片,可知,是大於的。
空間複雜度
和時間複雜度一樣,在計算空間複雜度時,O(n)就表示 程式正確執行完筆花費空間的增長趨勢,實際要比時間複雜度情景下簡單。
簡單練習
做個練習表示結束,分成兩講吧,快寫吐了。 比如,分析下列程式的時間和空間複雜度:
void atom(int n) { int arr[n]; int i; for (int i = 0; i < n; i++) { arr[i] = i; } } 複製程式碼
時間複雜度為:不論n多大,2,3行程式碼都是1次,第5行for迴圈體內是n次,第6行for迴圈體內為n次,所以總體為:n + n + 1 + 1,我們學習過,只看影響最大的,那麼就是 2n,進一步簡化成幾個基本函式,最終就是 n。所以:
時間複雜度為:O(n)。
空間複雜度為:i 之佔1個單位,arr 陣列佔n個,所以最終:
空間複雜度為:O(n)
更多JAVA系列教程可訪問: ofollow,noindex">blog.csdn.net/zhou307