您有没有想过,或者您是否可以使用多项式的Horner's representation?这不仅是计算多项式值的一种更有效的方法,而且在许多情况下可以导致更稀疏的数据结构。例如多项式:
等价于下面的表达式:
所以有3点需要注意:
- 实际上,此架构的一个显着之处(尽管与您的问题没有直接关系)是它的计算快得多,因为您节省了大量的乘法。
- 多项式的索引直接取决于表达式的长度
- 表达式中的所有元素都是同构,与度数无关。这对于每个 arity 也是如此。
所以在这个幸运的情况下,我选择的多项式可以非常容易且有效地存储为以下列表/数组:
[7, 5, 1, -4, 1, 8, 1, -7]
或者,如果您愿意,作为 [x_mult|sum] 数字的链表:
[7|5]->[1|4]->[1|8]->[1|-7]
虽然您知道具有偶数索引的元素乘以 x,并添加到后面的元素,但架构非常简单。
#include <iostream>
using namespace std;
int main()
{
// the x you want to calculate
int x = 1;
// the horner-representation of your polynom
int A[8] {7, 5, 1, -4, 1, 8, 1, -7};
int partial;
int result = 1;
// run calculations following horner-schema
for (int i = 0; i < 8; i++) {
if (i%2==0){
partial = A[i]*x; // this mult. is only needed at i=0
result *= partial;
} else{
partial = A[i];
result += partial;
}
}
cout << "x=" << x << ", p(x)=" << result << endl;
return 0;
}
问题:如果您抑制奇数索引,并且将“1”视为理所当然,将前 7 个存储在其他位置,则可以大大提高其性能和内存使用率。此外,由于索引直接取决于列表的长度,所以像 这样的多项式
将有一个非常低效的表示。
内存问题的解决方法:一种可能的解决方法是将您的 ListElement 继承为 ExpandedListElement,以便其容器中的数字不会被解释为因素,而是作为 数字重复次数。所以 ExpandedListElement [1000|a] 意味着,您的列表有一千个 ListElement,看起来像这样:[1|a]。所以给定的 x^1000+3 示例将有两个元素:ExpandedListElement[999|0]-->ListElement[1|3]。您还需要一个方法来执行循环,我省略了(如果您需要此解决方法,请告诉我,我会发布它)。
我没有对它进行广泛的测试,但我认为它对于两个或多个变量也是一种好方法。我也留下了其余的 OO 实现细节,但核心 DS 和操作在那里,应该很容易嵌入到类中。如果您尝试一下,请告诉我它是如何工作的!
干杯
安德烈斯