一、算法分析
如何判斷一個算法的好壞呢?首先算法必須要正確,這是最基本的要求。其次:
- 算法花費的時間
- 算法占用的空間小(輔助存儲空間)
- 算法要容易調試,測試,理解,編碼,維護等
二、時間復雜度
1、語句頻度
一個算法的執行時間理論上是無法計算出來的,只有上機測試才能知道。但實際上也沒有必要對所有算法上機測試(因為不同的計算機CPU情況是不一樣的),只需要知道在相同條件下,哪個算法執行的時間長就可以了。并且一個算法的執行時間與算法的語句執行次數成正比,比較語句的執行次數就可以了。
語句頻度是指該語句在整個算法執行過程中的執行次數,可以用所有語句的語句頻度之和來衡量一個算法的執行時間。
for (int i = 0; i < n; i++) {for (int j = 1; j < n; j++) {a = 0;}}
語句for (int i = 0; i < n; i++)的語句頻度為n+1,語句for (int j = 1; j < n; j++)的語句頻度為n的平方,語句a = 0的語句頻度為n*(n-1),所以該算法的語句頻度(相當于算法的時間耗費)為:T(n)=2*n的平方+1
2、時間復雜度
上面提到的時間頻度中,當n(問題規模)不斷變化時,T(n)也會不斷變化。為了弄清它變化時有什么規律,引入了時間復雜度的概念。
設T(n)的一個輔助函數為f(n),定義當n大于等于某一個正整數n0時,存在正的常數C,使得0<=T(n)<=Cf(n),則稱f(n)是T(n)的同數量級函數。把T(n)表示成數據量級的形式為:
T(n)=O(f(n))
其中O為Order(數據量級)的第一個字母,其含義是算法的執行時間T(n)與函數f(n)成正比。因此定義時間復雜度為T(n)=O(f(n)),f(n)一般是算法中所有語句中最大的語句頻度。
通常情況下,隨著問題規模n的增大,算法耗時T(n)增長最慢的算法是最優的算法。
下面舉例說明常見的時間復雜度:
- 常數階
int a = 1;
int b = 2;
int c = 3;
這類代碼即使有幾萬行十幾萬行,也不會隨著某個變量n的增加而增加。所以時間復雜度為:T(n)=O(1)
- 線性階
for(i=1; i<=n; i++) {j = i;j++;
}
j = i和j++都會執行n次,最大的語句頻度是n,所以時間復雜度為:T(n)=O(n)
- 對數階
int i = 1;
while(i < n) {i = i * 2;
}
語句i = i * 2會執行log2n次,最大的語句頻度是log2n,但是通常時間復雜度為:T(n)=O(logn),將底數給省略了。這是因為時間復雜度反應的是算法執行時間T(n)隨著問題規模n的變化規律,log2n是log3n的log23倍,log23是常數,所以log2n和log3n是同一數量級的,省略了底數之后同樣能反映這種變化規律。
- 平方階
for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {a = 0;}}
語句a=0會執行n的平方次,最大的語句頻度是n的平方,所以時間復雜度為:T(n)=O(n2)
ps:算法的執行時間有時候不光跟問題規模有關,還跟輸入的數據有關,不做說明的話,時間復雜度通常指的是數據最壞情況下的時間復雜度,因為算法的執行時間不可能超過最壞情況下的執行時間。
三、空間復雜度
由于數據實際占用空間與操作系統的軟件(編譯系統),硬件(字節)密切相關,故算法的實際占用空間無法準確判斷。通常衡量算法的空間使用情況不是實際占用空間,而是指整個算法用于輔助的存儲單元個數。
類似于時間復雜度的概念,可提出空間復雜度的概念來衡量算法占用的空間:
S(n)=O(f(n))