1. 程式人生 > 其它 >演算法的時間複雜度比較,計算多項式的直接法和秦九韶法

演算法的時間複雜度比較,計算多項式的直接法和秦九韶法

技術標籤:演算法java資料結構leetcode機器學習

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:

由實驗結果可以看出,秦九韶演算法幾乎都比普通演算法快一個數量級