演算法的時間複雜度比較,計算多項式的直接法和秦九韶法
阿新 • • 發佈:2021-02-09
1.直接法:
1 double Polynomial_1(int n, double a[], double x)
2 {
3 int i;
4 double sum = 0;
5 for (i = 0; i < n; i++)
6 sum += a[i] * pow(x, i);
7 return sum;
8 }
每次迴圈迭代,pow函式內部都會執行i次乘法,然後一次加法,所以整體的演算法複雜度為O = 1/2 * n ^ 2 + 3/2n,儘管pow函式的實現方法是利用遞迴優化後的,但是演算法複雜度還是達到了O(nlogn)
2.秦九韶法:
1 double Polynomial_2(int n, double a[], double x)
2 {
3 int i;
4 double sum = 0;
5 for (i = n; i > 0; i--)
6 sum = a[i - 1] + x * sum;
7 return sum;
8 }
它不斷提取公因式x來減少乘法的運算次數,演算法複雜度為O(n);
下面介紹一個測試執行時間的函式
clock()函式可以捕捉從程式開始執行到clock()被呼叫時所打下的點數,在要測試的函式前後各放置一個clock()函式,利用兩個clock()函式即可計算出執行一個函式所打下的點數,CLK_TCK(或者是CLOCKS_PER_SEC)是一個常量,表示一個機器時鐘每秒鐘所打下的點數,簡單計算後即可得到測試函式的執行時間,但是因為一個函式的執行時間是在是太短了,短到時鐘還來不及打下下一個點函式就執行結束了,所以我們讓被測函式重複迴圈多次執行,即可得到特定次數下的執行時間,被測函式的執行時間的比較就可以實現了。
1 void run(double(*f)(int, double*, double), double a[], int case_n) 2 { 3 //此函式用於測試被測函式(*f)的執行時間,並且根據case_n輸出相應的結果 4 //case_n是輸出的函式編號,1代表Polynomial_1, 2代表Polynomial_2 5 int i; 6 start = clock(); //開始計時 7 for (i = 0; i < MAXK; i++) //重複呼叫函式已獲得充分多的時鐘打點數 8 (*f)(MAXN, a, 1.1); 9 stop = clock(); //結束計時 10 duration = ((double)(stop - start)) / CLK_TCK; //計算執行時間 11 printf("ticks %d = %f\n", case_n, (double)(stop - start)); 12 printf("duration 1 = %6.2e\n", duration); 13 }
下面是主函式,設定了多項式的各項係數
1 #include <stdio.h>
2 #include <time.h>
3 #include <math.h>
4
5 clock_t start, stop;
6 double duration; //記錄被測函式執行的時間,以秒為單位
7 #define MAXN 10 //多項式最大項數,最大項數加1
8 #define MAXK 1e4 //被測函式最大重複呼叫次數
9
10 int main()
11 {
12 int i;
13 double a[MAXN];
14 for (i = 0; i < MAXN; i++) //設定多項式的各項係數
15 a[i] = (double)i;
16
17 run(Polynomial_1, a, 1);
18 run(Polynomial_2, a, 2);
19 return 0;
20
21 }
根據MAXK設定不同的值,讓被測函式重複迴圈執行相應的次數,實驗結果如下
10^4:
10^5:10^6:
10^7:由實驗結果可以看出,秦九韶演算法幾乎都比普通演算法快一個數量級