1. 程式人生 > >數據-第4課-審判程序的靈魂

數據-第4課-審判程序的靈魂

都是 依賴 出現 nbsp 三種 多次 size printf 對比

第4課-審判程序的靈魂

  1. 算法效率的度量

l 事後統計法

比較不同算法對同一組輸入數據的運行處理時間.

缺陷:

(1) 為了獲得不同算法的運行時間必須編寫相應程序.

(2) 運行時間嚴重依賴硬件以及運行時的環境因素.

(3) 算法的測試數據的選取相當困難。

事後統計法雖然直觀,但是實施困難且缺陷多 ,但是實施困難且缺陷多,一般不予考慮。

l 事前分析估算

依據統計的方法對算法效率進行估算。

l 影響算法效率的主要因素

(1) 算法采用的策略和方法。

(2) 問題的輸入規模。

(3) 編譯器所產生的代碼。

(4) 計算機執行速度。

算法效率的簡單估算

  1. 算法效率的估量

例子:二重循環估算

#include <stdio.h>

int func(int a[], int len)

{

int i = 0;

int j = 0;

int s = 0;

for(i=0; i<len; i++)

{

for(j=0; j<len; j++)

{

s += i*j;

}

}

return s;

}

int main()

{

int array[] = {1, 2, 3, 4, 5};

printf("%d\n", func(array, 5));

return 0;

}

估算時間:t = (n2 + 2) T

啟示

(1) 練習中的程序關鍵部分的操作數量為n*n

(2) 三種求和算法中求和的關鍵部分的操作數量分別為2n, n1

隨著問題規模n的增大,它們操作數量的差異也會越來越大,因此實際算法在時間效率上也會變得非常明顯!

不同算法操作數量的對比

判斷一個算法的效率時,往往只需要關註操作數量的最高次項,其它次要項和常數項可以忽略。

l O表示法

(1) 算法效率嚴重依賴於操作(Operation)數量。

(2) 在判斷時首先關註操作數量的最高次項。

(3) 操作數量的估算可以作為時間復雜度的估算。

O(5) = O(1)

O(2n + 1) = O(2n) = O(n)

O(n2 + n + 1) = O(n2)

O(3n3+1) = O(3n3) = O(n3)

常見時間復雜度類型

關系:O(1) < O(logn) < O(n) < O(nlogn) < o(n2) < O(n3) < O(2n) < O(n!) < O(nn)

  1. 最好與最壞

例子:

#include <stdio.h>

int search(int array[], int length, int n)

{

int ret = -1;

int i = 0;

for(i=0; i<length; i++)

{

if( array[i] == n )

{

ret = i;

break;

}

}

return ret;

}

int main()

{

int array[5] = {1, 2, 3, 4, 5};

printf("%d\n", search(array, 5, 1)); //O(1),一次就好

printf("%d\n", search(array, 5, 5)); //O(n)n次才好

return 0;

}

意義:

當算法在最壞情況下仍然能滿足需求時,可以推斷,算法的最好情況和平均情況都滿足需求。

在沒有特殊說明時,我們所分析的算法的時間復雜度都是指最壞時間復雜度。

  1. 算法的空間復雜度

算法的空間復雜度通過計算算法的存儲空間實現

S(n) = S(n) = ) =O(f(n))

其中,n為問題規模,f(n)為在問題規模為n時所占用存儲空間的函數。

空間復雜度表示申請的空間大小,大O表示法同樣適用於算法的空間復雜度。當算法執行時所需要的空間是常數時,空間復雜度為O(1),為n時是O(n)

  1. 空間與時間的策略

(1) 多數情況下,算法執行時所用的時間更令人關註。

(2) 如果有必要,可以通過增加空間復雜度來降低時間復雜度。

(3) 同理,也可以通過增加時間復雜度來降低空間復雜度。

l 在實現算法時需要分析具體問題對執行時間和空間的要求。

例子:

#include <stdio.h>

/*

問題:

在一個由自然數1-1000中某些數字所組成的數組中,每個數字可能出現零次或者多次。

設計一個算法,找出出現次數最多的數字。

*/

void search(int a[], int len)

{

int sp[1000] = {0};

int i = 0;

int max = 0;

for(i=0; i<len; i++)

{

int index = a[i] - 1;

sp[index]++;

}

for(i=0; i<1000; i++)

{

if( max < sp[i] )

{

max = sp[i];

}

}

for(i=0; i<1000; i++)

{

if( max == sp[i] )

{

printf("%d\n", i+1);

}

}

}

int main()

{

int array[] = {1, 1, 3, 4, 5, 6, 6, 6, 2, 3};

search(array, sizeof(array)/sizeof(*array));

return 0;

}

這個算法很好。

思考:

當兩個算法的大O表示法相同的時候,是否意味著兩個算 ,是否意味著兩個算法的效率完全相同?

數據-第4課-審判程序的靈魂