霍纳法则解决的是计算机数值运算的问题,但是没有解决代数运算的问题。
我们举个例子,以下多项式的乘法。
(
2
x
2
+
4
x
+
7
)
(
3
x
2
+
6
x
+
1
)
(
5
x
2
+
8
x
+
9
)
(2x^2+4x+7)(3x^2+6x+1) (5x^2+8x+9)
(2x2+4x+7)(3x2+6x+1)(5x2+8x+9)
首先是要定义数据结构。前面霍纳法则是用数组来表示一个多项式,所以这种多项式的乘法完全可以用矩阵来表示。比如上面的例子可以写成矩阵:
(
2
4
7
3
6
1
5
8
9
)
\begin{pmatrix} 2 & 4 & 7\\ 3 & 6 & 1\\ 5 & 8 & 9 \end{pmatrix}
⎝⎛235468719⎠⎞
那么前两项的乘积就是:
2
×
3
x
4
+
2
×
6
x
3
+
4
×
3
x
3
+
7
×
3
x
2
+
2
×
1
x
2
+
4
×
6
x
2
+
4
×
1
x
+
6
×
7
x
+
7
×
1
2\times3x^4+ 2\times6x^3 + 4\times3x^3 + 7\times3x^2+ 2\times1x^2+4\times6x^2+4\times1x+6\times7x+7\times1
2×3x4+2×6x3+4×3x3+7×3x2+2×1x2+4×6x2+4×1x+6×7x+7×1
前两项的乘积再和第三个式子相乘,就是27项相加。
最基本的算法是
O
(
m
n
)
O(mn)
O(mn)复杂度的算法。
最基本的步骤是:
先求出最高次,假设每个多项式次数为m,多项式个数为n,那么最大次数为
m
×
n
m\times n
m×n。数组的长度就是
m
×
n
+
1
m\times{n}+1
m×n+1。每个多项式的数组长度为为m+1。所以如果每个多项式数组size为s。那么最终结果数组长度就是
(
s
−
1
)
×
n
+
1
(s-1)\times n+1
(s−1)×n+1。
然后对这个矩阵进行遍历,假设行索引为l,列索引为c,矩阵为m。结果数组为result
首先用变量p代表次数(几次幂),然后用pi代表乘积。
p+=(s-c-1)
Pi*=m[l][c]
Result[result.length – p -1] += pi
最后的结果就是了。
但是这个遍历不是简单的遍历,因为我们知道复杂度是O(mn),而双层循环遍历的复杂度是O(mn),所以这里要用到递归或者树的遍历。
可以使用深度搜索算法实现一下。以上述矩阵为例子,是这样一棵树:
这棵树,我就不画完了,浪费篇幅。具体就是树的遍历了。
首先是定义一个栈stack,元素为{层数,元素}的一个复杂对象。
然后是将第一组逆序压入栈
再将每个要取自己的孩子。要取孩子就需要知道自己在第几层,所以压入栈内的元素不能单纯是元素,还应该包含层数。所以要造个对象,这个对象的名字就叫做Node
所以获取孩子的办法就是取层数,层数+1,然后从原数组里取,那么拿到之后是这个顺序2 3 5,需要把这个连乘起来。也就是说只有在最后一层时才进行连乘操作。如果连乘到了最下面一层,也就是没有结尾了,就需要处理了,把p和pi清空
试验数据
(
x
+
2
)
(
3
x
+
4
)
=
3
x
2
+
10
x
+
8
(x+2)(3x+4)=3x^2+10x+8
(x+2)(3x+4)=3x2+10x+8,python代码如下:
# 多项式
class Node:
def __init__(self, line, column, element, parent):
self.__line = line
self.__column = column
self.__element = element
self.__parent = parent
@property
def line(self):
return self.__line
@property
def column(self):
return self.__column
@property
def element(self):
return self.__element
@property
def parent(self):
return self.__parent
def polynomial_simplify(matrix):
# 把一组多项式化简为一个多项式
# 首先要定义一个结果数组
n = len(matrix)
m = len(matrix[0])
result = [0] * ((m - 1) * n + 1)
# 利用树的深度遍历
stack = [Node(0, i, e, None) for i, e in enumerate(matrix[0])]
# 定义连乘数变量
while len(stack) > 0:
# 取出进行处理
node = stack.pop()
line = node.line
column = node.column
element = node.element
print(f'element={element}')
if line == (n - 1):
# 遍历所有parent
pi = 1
p = 0
node_pointer:Node = node
while node_pointer is not None:
pi *= node_pointer.element
p += m - node_pointer.column - 1
node_pointer = node_pointer.parent
result[len(result) - p - 1] += pi
# 处理完了,就把children放进去
else:
for c, e in enumerate(matrix[line + 1]):
stack.append(Node(line + 1, c, e, node))
return result