一. 概念引入
1.定義
(1)x 的 n 次多項式: P(x) = anxn + an-1xn-1 + ... + a1x + a0。(其中 x 是底數, n 是指數, ai 是每一項前面的系數, 0 ≤ i ≤ n ,並且最高次項前面的系數不為 0 )
2. 實例分析
(1)求 xn 的方法:
xn = x · x · … · x (共 n 個 x ),顯然,式子中執行了 n - 1 次乘法。
取 x = 2, n = 3 時,該項為 23 = 2 × 2 × 2,可以看出,執行了 2 次乘法。
(2)求 x 的 n 次多項式的方法:
假設有多項式 P(x) = anxn + an-1xn-1 + ... + a1x + a0。先看第一項 anxn ,其中 xn 執行了 n - 1 次乘法,再與 an 相乘,共執行 n 次乘法。其余各項同理。
取 x = 2, n = 4, 系數為 1 時, P(2) = 24 + 23 + 22 + 21 + 1
二. 多項式求值常規算法
繼續以上例來說明問題:取 x = 2, n = 4, 系數為 1 時, P(2) =24 + 23 + 22 + 21 + 1。
當我們用正常思路去計算,即先算第一項,再算第二項,直到算出每項結果,最后將各項結果相加。先算第一項: 2 × 2 × 2 × 2 ,再算第二項: 2 × 2 × 2, 再算第三項: 2 × 2。該算法的時間復雜度是 O(n2)。我們可以發現,其中有很多重復步驟。第一項已經做完了大部分工作,其余項為什么要把第一項的勞動成果棄之不用呢?
三. 霍納法則
霍納將多項式進行變形:P(x) = a3x3 + a3x2 + a1x + a0 → P(x) = x ( x ( x ( a3 ) + a2 ) + a1 ) + a0 ,這樣執行多項式求值,每一次的結果都能得到充分的利用,不難看出,霍納算法的時間復雜度是 O( n )
四. 代碼實現
1. 常規算法
這里我手動實現了一個函數 cal_power,用於計算 x 的 n 次方。
1 int cal_power(int x, int n) { 2 int product = x; 3 for (int i = 0; i < n - 1; ++i) { 4 product *= x; 5 } 6 7 return product; 8 } 9 10 int cal_ploy (vector<int> &coefficient, int x, int n) { 11 int sum = coefficient[ n ]; 12 for (int i = 0; i < n; ++i) { 13 int item = coefficient[ i ] * cal_power(x, n - i); 14 sum += item; 15 } 16 17 return sum; 18 }
2.霍納法則
1 int honour_rule(vector<int> &coefficient, int x, int n) { 2 int sum = coefficient[0]; 3 for (int i = 1; i <= n; ++i) { 4 sum = x * sum + coefficient[i]; 5 } 6 7 return sum; 8 }
3.測試
1 int main() { 2 int x, n, result; 3 cout << "Enter x, n : "; 4 cin >> x >> n; 5 vector<int> coefficients; 6 7 for (int i = 0; i <= n; ++i) { 8 int current_num; 9 cout << "coefficient " << (i + 1) << " : "; 10 cin >> current_num; 11 coefficients.push_back(current_num); 12 } 13 14 result = cal_ploy(coefficients, x, n); 15 cout << "regular sum = " << result << endl; 16 17 result = honour_rule(coefficients, x, n); 18 cout << "honour rule sum = " << result << endl; 19 20 cout << "Done." << endl; 21 22 return 0; 23 }
其中需要說明幾點:
第一,代碼中沒有錯誤處理,邊界檢查,默認輸入沒有問題,這樣做只是為了清楚地說明算法思路,略去了算法無關的內容,但是實際操作中,這些代碼必不可少。
第二,用 vector 來保存系數,在輸入時,按照表達式的系數順序輸入即可,不用從后往前輸入。