【Weiss】【第03章】练习3.7:有序多项式相乘

【练习3.7】

编写一个函数将两个多项式相乘,用一个链表实现。你必须保证输出的多项式按幂次排列,并且任意幂次最多只有一项。

a.给出以O(M2N2)时间求解该问题的算法。

b.写一个以O(M2N)时间执行乘法的程序,其中M≤N。

c.写一个以O(MNlog(MN))时间执行乘法的程序。

d.上面哪个时间界最好?

 

 

Answer:

【a】.将两链表元素两两相乘并列出,从第一项开始,依次与其后的所有项比较,如相等则合并。

合并完成后,每次找出幂次最小的项,插入链表。(最原始的方法)

【b】.M≤1时,方法易知。

M≥2时,每次将长度为M的链表的一项,与另一链表的所有项相乘,每次一组N个有序的多项式元素。

对于每两组上式的N个多项式元素,基本按练习3.5有序链表求并的算法(除幂次相同需将系数相加)操作。

求并算法时间复杂度O(M+N),故该算法复杂度为

(乘法时间)O(MN)+(求并时间)O((N+N)+(2N+N)+(3N+N)+……+(MN+N))=O(M2N)

【详情见代码】

【c】.同a先将两链表元素两两相乘并列出,对MN项元素进行O(NlogN)的排序

排序完成后,遍历代码,合并同幂次项,最后全部插入链表。时间复杂度为:

(乘法时间)O(MN)+(排序时间)O(MNlogMN)+(合并同类项时间)O(MN)=O(MNlogMN)

【详见代码】

 

代码部分,首先是测试代码,b和c的测试代码写在一起了

 1 #include <iostream>
 2 #include "linklist.h"
 3 using linklist::List;
 4 using namespace std;
 5 int main(void)
 6 {
 7     //测试多项式加法
 8     List<Poly> a;
 9     a.additem(Poly(3, 1));
10     a.additem(Poly(1, 2));
11     a.additem(Poly(4, 3));
12     a.additem(Poly(7, 4));
13     a.additem(Poly(2, 5));
14     cout << "  ( " << flush;
15     a.traverse();
16     cout << ")  +\n" << flush;
17     List<Poly> b;
18     b.additem(Poly(5, 2));
19     b.additem(Poly(2, 3));
20     b.additem(Poly(1, 5));
21     b.additem(Poly(3, 7));
22     b.additem(Poly(1, 11));
23     cout << "  ( " << flush;
24     b.traverse();
25     cout << ") =\n" << flush;
26 
27     List<Poly> answer = linklist::polymulti_seq(a, b);
28     List<Poly> another = linklist::polymulti_sort(a, b);
29     cout << "\n  ( " << flush;
30     answer.traverse();
31     cout << ") \n" << flush;
32 
33     cout << "\n  ( " << flush;
34     another.traverse();
35     cout << ") \n" << flush;
36     system("pause");
37 }
View Code

实现部分,首先需在poly.h中重载多项式元素的乘法运算符

1 //练习3.7新增,多项式元素乘法*
2 Poly operator*(const Poly& poly1, const Poly& poly2)
3 {
4     Poly answer;
5     answer.coefficient = poly1.coefficient*poly2.coefficient;
6     answer.exponent = poly1.exponent + poly2.exponent;
7     return answer;
8 }

然后是小题b代码,包括习题3.5求并成员函数的模板特例化的辅助函数及主相乘算法

 1 //练习3.7b新增,将3.5求并的成员函数特例化
 2 template <> void List<Poly>::join(List<Poly> inorder)
 3 {
 4     Node<Poly>* curr = front;
 5     Node<Poly>* prev = nullptr;
 6     Node<Poly>* curr2 = inorder.front;
 7     while (curr != nullptr && curr2 != nullptr)
 8     {
 9         if (curr->data < curr2->data)
10         {
11             prev = curr;
12             curr = curr->next;
13         }
14         else if (curr2->data < curr->data)
15         {
16             additem(curr2->data, prev);
17             if (prev == nullptr)
18                 prev = front;
19             else
20                 prev = prev->next;
21             curr2 = curr2->next;
22         }
23         else
24         {
25             //对比3.5唯一增加语句
26             //当两元素幂次相等时,原链表与新链表的多项式系数相加并将指针后移
27             curr->data = curr->data + curr2->data;
28             prev = curr;
29             curr = curr->next;
30             curr2 = curr2->next;
31         }
32     }
33     while (curr2 != nullptr)
34     {
35         additem(curr2->data, prev);
36         if (prev == nullptr)
37             prev = front;
38         else
39             prev = prev->next;
40         curr2 = curr2->next;
41     }
42 }
43 
44 //练习3.7b新增,以O(M²N)时间执行多项式乘法
45 List<Poly> polymulti_seq(const List<Poly> &inorder_a, const List<Poly> &inorder_b)
46 {
47     //保证首链表长度较小
48     if (inorder_a.size() > inorder_b.size())
49         return polymulti_seq(inorder_b, inorder_a);
50     else
51     {    
52         List<Poly> answer;
53         for (Node<Poly>* iter_a = inorder_a.begin(); iter_a != nullptr; iter_a = iter_a->next)
54         {
55             //用较短链表中每一个元素乘较长链表,得到临时链表
56             {
57                 List<Poly> temp;
58                 for (Node<Poly>* iter_b = inorder_b.begin(); iter_b != nullptr; iter_b = iter_b->next)
59                     temp.additem(iter_a->data * iter_b->data);
60                 answer.join(temp);
61             }
62         }
63         return answer;
64     }
65 }

然后为c小题算法,调用了标准库中的快排,需要#include<algorithm>

 1 //练习3.7c新增,以O(MNlogMN)时间执行多项式乘法
 2 List<Poly> polymulti_sort(const List<Poly> &inorder_a, const List<Poly> &inorder_b)
 3 {
 4     unsigned maxsize = inorder_a.size() * inorder_b.size();
 5     //申请M*N大小的数组
 6     Poly* temp_array = new Poly[maxsize];
 7     unsigned int index = 0;
 8     //依次对链表每两个节点元素相乘并放在数组中
 9     for (Node<Poly>* iter_a = inorder_a.begin(); iter_a != nullptr; iter_a = iter_a->next)
10         for (Node<Poly>* iter_b = inorder_b.begin(); iter_b != nullptr; iter_b = iter_b->next)
11             temp_array[index++] = iter_a->data*iter_b->data;
12     //对数组进行升序快排
13     sort(&temp_array[0], &temp_array[--index]);
14     List<Poly> answer;
15     //单次遍历数组,合并同类项
16     for (index = 1; index < maxsize; ++index)
17     {
18         if (temp_array[index] == temp_array[index - 1])
19             temp_array[index] = temp_array[index - 1] + temp_array[index];
20         else
21             answer.additem(temp_array[index - 1]);
22     }
23     answer.additem(temp_array[index - 1]);
24     delete[] temp_array;
25     return answer;
26 }

 

posted @ 2015-03-12 00:01  猫薄荷喂狗  阅读(1014)  评论(0编辑  收藏  举报