Polynomial ADT

对于一个多项式,需要处理的数据有每一项的幂级数,以及该项的系数。

1. 数组实现

这是比较简单的一种方法,先看多项式的数据结构:

typedef struct _polynomial
{
    int high_power;
    /* +1 because there is constant term. */
    int coff_array[MAX_DEGREE + 1]; 
} *Polynomial;

在上述数据结构中:

  1. high_power是该多项式的最高项的次数;
  2. coff_array是系数数组,且下标对应次数

有了上面的数据结构,多项式的加法、减法、乘法都可以一一实现了,伪代码如下:

add_polynomial(poly1, poly2, poly_sum):
	max_power = max{poly1.high_power, poly2.high_power}.
	for i from 0 to max_power:
		poly_sum.coff_array[i] = 
		poly2.coff_array[i] + poly1.coff_array[i]

multi_polynomial(poly1, poly2, poly_prod):
	for i from 0 to poly1.high_power:
		for j from 0 to poly2.high_power:
			poly_sum.coff_array[i * j] += 
			poly1.coff_array[i] * poly2.coff_array[j]

因为减法与加法几乎完全一样,不再赘述。
可以注意到的是,由于使用下标作为系数,所以无法表示 2 2 3 2^{\frac{2}{3}} 232一类的项。这也是无法实现除法的主要原因。

算法复杂度:
add_polynomial()0遍历到high_power,取决于两个poly中较大的high_power
multi_polynomail()两重遍历,都是从0遍历到high_power,为 O ( m n ) O(mn) O(mn),其中 m m m n n n分别是两个乘数多项式的最高次幂。

2. 链表实现

除了不能使用除法,数组实现还有一些小的问题,比如有最高次幂的限制。最重要的一点是,如果多项式的大多数次幂的系数都为0,即coff_array中的大多数元素值都为0,那么在系数为0的数据上会花费很多时间。比如 p 1 = x 2001 + 7 x 1000 + 5 p_1 = x^{2001} + 7x^{1000} + 5 p1=x2001+7x1000+5 p 2 = 10 x 2308 + 66 p_2 = 10x^{2308} + 66 p2=10x2308+66,那么 p 1 × p 2 p_1 \times p_2 p1×p2的计算过程中会有大量的 0 × 0 0 \times 0 0×0的操作。
如果采用链表的方式,那么上述问题都可以解决了,先来看一下节点的数据结构:

typedef struct Node *Ptr_Node;
typedef Ptr_Node Polynomial;
typedef Polynomial List;

struct Node
{
	int coffient;
	int degree;
	Ptr_Node next_node;
};

其中coffient表示当前节点的系数,degree表示当前节点的次幂。然后加法和乘法的伪代码如下所示:

add_polynomial(poly1, poly2, poly_sum):
	for n1 in poly1 and n2 in poly2:
		if n1.degree < n2.degree:
			poly_sum.append(n1)
			n1 = n2->next
		else if n1.degree > n2.degreee:
			poly_sum.append(n2)
			n2 = n2.next
		else if n1.degree == n2.degree:
			n3.degree = n1.degree
			n3.coffient = n1.coffient + n2.coffient
			poly_sum.append(n3)
			n1 = n1.next
			n2 = n2.next

multi_polynomail(poly1, poly2, poly_prod):
	for n1 in poly1:
		for n2 in poly2:
			n3.degree = n1.degree + n2.degreee
			n3.coffient = n1.coffient * n2.coffient
			for np in prod:
				if np.degree == n3.degree:
					np.coffient += ne.coffient
			if didn't find np.degree = n3.degree:
				insert n3 to appropriate position of poly_prod	

减法与除法依旧是与加法和乘法类似的操作,不再赘述。

算法复杂度:
add_polynomial()复杂度为 O ( m + n ) O(m + n) O(m+n),其中 m m m n n n分别是两个加数多项式项的个数,一般多数情况下,多项式个数小于最高次幂。
multi_polynomial()外部是两层循环,复杂度为 O ( m n ) O(mn) O(mn);内部的for循环次数从1开始,最多增长到m * n,复杂度为
1 + 2 + 3 + . . + m n = ∑ i = 1 m n i = m n ( m n + 1 ) 2 = O ( m 2 n 2 ) 1 + 2 + 3 + .. + mn = \sum_{i=1}^{mn}{i} = \frac{mn(mn + 1)}{2} = O(m^2n^2) 1+2+3+..+mn=i=1mni=2mn(mn+1)=O(m2n2)
所以总的时间复杂度为 O ( m 3 n 3 ) O(m^3n^3) O(m3n3)
乘法的复杂度感觉算得有点问题,如果有哪位大佬能算出准确界,还望告知。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值