1.算法耗費的時間、語句頻度、輸入規模
在實際中,一個算法所需耗費的時間 = 算法中所有語句的執行時間之和
而,每條語句的執行時間 = 每條語句執行一次所需時間 * 每條語句的執行次數(語句頻度)
因爲每條語句執行一次所需時間取決於機器執行指令的性能、速度等難以確定的因素,而爲了獨立於機器的軟、硬件系統來分析算法的時間耗費,
我們假設每條語句執行一次所需時間均爲單位時間,那麼,一個算法的時間規模就與其所有語句的頻度之和相關。
輸入規模:算法求解問題的輸入量稱爲問題的規模,一般用一整數來表示:n = 1, 2, 3 ...k
那麼,對於輸入規模爲 n 的算法,其語句頻度之和可記作:T(n)
(1) for(i=0; i<n;j++) n+1 (2) for (j=0;j<n;j++) { n(n+1) (3) C[i][j]=0; n^2(表示n的平方) (4) for (k=0; k<n; k++) n^2(n+1) (5) C[i][j]=C[i][j]+A[i][k]*B[k][j]; n^3
分析:
語句(1)的循環控制變量i要增加到n,測試到i=n成立纔會終止。故它的頻度是n+1。但是它的循環體卻只能執行n次。
語句(2)作爲語句(1)循環體內的語句應該執行n次,但語句(2)本身要執行n+1次,所以語句(2)的頻度是n(n+1)。
同理可得語句(3),(4)和(5)的頻度分別是n2,n2(n+1)和n3。
該算法中所有語句的頻度之和(即算法的時間耗費)爲: T(n)=2n^3+3n^2+2n+1
2. 時間複雜度
概念:
如某算法的語句頻度之和爲 T(n),那麼,當 n 趨於無窮大虹,若存在函數 f(n)使得 T(n)/f(n)的極限值爲不等於0的常數,
則稱: f(n) 是 T(n) 的同數量級函數,記作:T(n) = O(f(n))
稱: O(f(n)) 爲該算法的漸進時間複雜度,簡稱:時間複雜度
舉例說明時間複雜度的求法:
交換i和j的內容。
Temp=i;
i=j;
j=temp;
以上三條單個語句的頻度均爲1,該程序段的執行時間是一個與問題規模n無關的常數。算法的時間複雜度爲常數階,記作T(n)=O(1)。
注意:
如果算法的執行時間不隨着問題規模n的增加而增長,即使算法中有上千條語句,其執行時間也不過是一個較大的常數。此類算法的時間複雜度是O(1)。
變量計數之一:
(1) x=0;y=0;
(2) for(k-1;k<=n;k++)
(3) x++;
(4) for(i=1;i<=n;i++)
(5) for(j=1;j<=n;j++)
(6) y++;
一般情況下,對步進循環語句只需考慮循環體中語句的執行次數,忽略該語句中步長加1、終值判別、控制轉移等成分。
因此,以上程序段中頻度最大的語句是(6),其頻度爲f(n)=n^2,所以該程序段的時間複雜度爲T(n)=O(n^2)。
當有若干個循環語句時,算法的時間複雜度是由嵌套層數最多的循環語句中最內層語句的頻度f(n)決定的。
變量計數之二:
(1) x=1;
(2) for(i=1;i<=n;i++)
(3) for(j=1;j<=i;j++)
(4) for(k=1;k<=j;k++)
(5) x++;
該程序段中頻度最大的語句是(5),內循環的執行次數雖然與問題規模n沒有直接關係,但是卻與外層循環的變量取值有關,而最外層循環的次數直接與n有關,
因此可以從內層循環向外層分析語句(5)的執行次數n^3,得出該算法時間複雜度爲T(n)=O(n^3/6+低次項)=O(n^3)。
注意:
算法的時間複雜度不僅僅依賴於問題的規模,還與輸入實例的初始狀態有關。
在數值A[0..n-1]中查找給定值K的算法大致如下:
(1)i=n-1;
(2)while(i>=0&&(A[i]!=k))
(3) i--;
(4)return i;
此算法中的語句(3)的頻度不僅與問題規模n有關,還與輸入實例中A的各元素取值及K的取值有關:
①若A中沒有與K相等的元素,則語句(3)的頻度f(n)=n;
②若A的最後一個元素等於K,則語句(3)的頻度f(n)是常數0。
3.最壞時間複雜度和平均時間複雜度
最壞情況下的時間複雜度稱最壞時間複雜度。一般不特別說明,討論的時間複雜度均是最壞情況下的時間複雜度。
這樣做的原因是:最壞情況下的時間複雜度是算法在任何輸入實例上運行時間的上界,這就保證了算法的運行時間不會比任何更長。
平均時間複雜度是指所有可能的輸入實例均以等概率出現的情況下,算法的期望運行時間。
常見的時間複雜度按數量級遞增排列依次爲:
常數階 O(1)
對數階 O(log2n)
線性階 O(n)
線性對數階 O(nlog2n)
平方階 O(n2)
立方階 O(n3)
…
k次方階 O(nk)
指數階 O(2n)