【练习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的测试代码写在一起了

 #include <iostream>
#include "linklist.h"
using linklist::List;
using namespace std;
int main(void)
{
//测试多项式加法
List<Poly> a;
a.additem(Poly(, ));
a.additem(Poly(, ));
a.additem(Poly(, ));
a.additem(Poly(, ));
a.additem(Poly(, ));
cout << " ( " << flush;
a.traverse();
cout << ") +\n" << flush;
List<Poly> b;
b.additem(Poly(, ));
b.additem(Poly(, ));
b.additem(Poly(, ));
b.additem(Poly(, ));
b.additem(Poly(, ));
cout << " ( " << flush;
b.traverse();
cout << ") =\n" << flush; List<Poly> answer = linklist::polymulti_seq(a, b);
List<Poly> another = linklist::polymulti_sort(a, b);
cout << "\n ( " << flush;
answer.traverse();
cout << ") \n" << flush; cout << "\n ( " << flush;
another.traverse();
cout << ") \n" << flush;
system("pause");
}

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

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

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

 //练习3.7b新增,将3.5求并的成员函数特例化
template <> void List<Poly>::join(List<Poly> inorder)
{
Node<Poly>* curr = front;
Node<Poly>* prev = nullptr;
Node<Poly>* curr2 = inorder.front;
while (curr != nullptr && curr2 != nullptr)
{
if (curr->data < curr2->data)
{
prev = curr;
curr = curr->next;
}
else if (curr2->data < curr->data)
{
additem(curr2->data, prev);
if (prev == nullptr)
prev = front;
else
prev = prev->next;
curr2 = curr2->next;
}
else
{
//对比3.5唯一增加语句
//当两元素幂次相等时,原链表与新链表的多项式系数相加并将指针后移
curr->data = curr->data + curr2->data;
prev = curr;
curr = curr->next;
curr2 = curr2->next;
}
}
while (curr2 != nullptr)
{
additem(curr2->data, prev);
if (prev == nullptr)
prev = front;
else
prev = prev->next;
curr2 = curr2->next;
}
} //练习3.7b新增,以O(M²N)时间执行多项式乘法
List<Poly> polymulti_seq(const List<Poly> &inorder_a, const List<Poly> &inorder_b)
{
//保证首链表长度较小
if (inorder_a.size() > inorder_b.size())
return polymulti_seq(inorder_b, inorder_a);
else
{
List<Poly> answer;
for (Node<Poly>* iter_a = inorder_a.begin(); iter_a != nullptr; iter_a = iter_a->next)
{
//用较短链表中每一个元素乘较长链表,得到临时链表
{
List<Poly> temp;
for (Node<Poly>* iter_b = inorder_b.begin(); iter_b != nullptr; iter_b = iter_b->next)
temp.additem(iter_a->data * iter_b->data);
answer.join(temp);
}
}
return answer;
}
}

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

 //练习3.7c新增,以O(MNlogMN)时间执行多项式乘法
List<Poly> polymulti_sort(const List<Poly> &inorder_a, const List<Poly> &inorder_b)
{
unsigned maxsize = inorder_a.size() * inorder_b.size();
//申请M*N大小的数组
Poly* temp_array = new Poly[maxsize];
unsigned int index = ;
//依次对链表每两个节点元素相乘并放在数组中
for (Node<Poly>* iter_a = inorder_a.begin(); iter_a != nullptr; iter_a = iter_a->next)
for (Node<Poly>* iter_b = inorder_b.begin(); iter_b != nullptr; iter_b = iter_b->next)
temp_array[index++] = iter_a->data*iter_b->data;
//对数组进行升序快排
sort(&temp_array[], &temp_array[--index]);
List<Poly> answer;
//单次遍历数组,合并同类项
for (index = ; index < maxsize; ++index)
{
if (temp_array[index] == temp_array[index - ])
temp_array[index] = temp_array[index - ] + temp_array[index];
else
answer.additem(temp_array[index - ]);
}
answer.additem(temp_array[index - ]);
delete[] temp_array;
return answer;
}

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

  1. 第03章 AOP前奏

    第03章 AOP前奏 提出问题 ●情景:数学计算器 ●要求 ①执行加减乘除运算 ②日志:在程序执行期间追踪正在发生的活动 ③验证:希望计算器只能处理正数的运算 ●常规实现 ●问题 ○代码混乱:越来越多 ...

  2. 第03章_基本的SELECT语句

    第03章_基本的SELECT语句 1. SQL概述 1.1 SQL背景知识 1946 年,世界上第一台电脑诞生,如今,借由这台电脑发展起来的互联网已经自成江湖.在这几十年里,无数的技术.产业在这片江湖 ...

  3. suse 12 二进制部署 Kubernetets 1.19.7 - 第03章 - 部署flannel插件

    文章目录 1.3.部署flannel网络 1.3.0.下载flannel二进制文件 1.3.1.创建flannel证书和私钥 1.3.2.生成flannel证书和私钥 1.3.3.将pod网段写入et ...

  4. 【Weiss】【第03章】练习3.8:有序多项式求幂

    [练习3.8] 编写一个程序,输入一个多项式F(X),计算出(F(X))P.你程序的时间复杂度是多少? Answer: (特例:P==0时,返回1.) 如果P是偶数,那么就递归计算((F(X))P/2 ...

  5. 【Weiss】【第03章】练习3.6:有序多项式相加

    [练习3.6] 编写将两个多项式相加的函数.不要毁坏输入数据.用一个链表实现. 如果这两个多项式分别有M项和N项,那么你程序的时间复杂度是多少? 两个按幂次升序的多项式链表,分别维护一个指针. 幂较小 ...

  6. 【Weiss】【第03章】练习3.4、3.5:有序链表求交、并

    [练习3.4] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∩L2的过程. [练习3.5] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∪L2的过程. 思路比较简单,测 ...

  7. 【Weiss】【第03章】练习3.16:删除相同元素

    [练习3.16] 假设我们有一个基于数组的表A[0,1...N-1],并且我们想删除所有相同的元素. LastPosition初始值为N-1,但应该随着相同元素被删除而变得越来越小. 考虑图3-61中 ...

  8. 【Weiss】【第03章】增补附注

    基本上每章到增补附注这里就算是结束了. 根据设想,每章的这一篇基本上会注明这一章哪些题没有做,原因是什么,如果以后打算做了也会在这里补充. 还有就是最后会把有此前诸多习题的代码和原数据结构放整理后,以 ...

  9. 【Weiss】【第03章】练习3.25:数组模拟队列

    [练习3.25] 编写实现队列的例程,使用 a.链表 b.数组 Answer: 在这章一开头就已经写了个链表的队列例程了,所以实际上只要做b小题就可以. 数组模拟队列和链表的两点小不同是: ①.数组空 ...

随机推荐

  1. ionic3 生命周期钩子

    ionViewDidLoad 页面加载完成触发,这里的"加载完成"指的是页面所需的资源已经加载完成,但还没进入这个页面的状态(用户看到的还是上一个页面). 需要注意的是它是一个很傲 ...

  2. DailyRollingFileAppender-设置文件大小和备份天数

    感谢:http://byx5185.iteye.com/blog/1616034 1.重写FileAppender : package com.bankht.cis.tps.apps.tps.util ...

  3. git clone 新项目时,报error: RPC failed; curl 18 transfer closed with outstanding read data remaining

    error: RPC failed; curl 18 transfer closed with outstanding read data remaining fatal: The remote en ...

  4. maven工程根项目运行ok但是子项目就报错的解决办法

    正常启动没错 项目出现问题 maven工程根项目运行ok但是子项目就报错 报错信息是xxxx没有创建 解决办法 原来是子项目的依赖少了  没有配置1.8  所以会出现莫明其妙的bug

  5. python基础 生成器 迭代器

    列表生成式: a=[1,2,3] print a b=[i*2 for i in range(10)] #i循环10次,每一个i的值乘2就是列表中的值.列表生成式 print b >>[1 ...

  6. 【深圳·招聘】QQ音乐测试工程师-职位内推

    QQ音乐测试工程师 岗位职责 负责腾讯QQ音乐移动端/后台/web相关特性测试分析和执行,保障发布质量. 岗位要求 专业本科及以上学历,计算机/软件工程/信息管理/数学与应用数学/自动化/通信工程/电 ...

  7. RxJava 2.x 源码分析

    本次分析的 RxJava 版本信息如下: 12 implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'implementation 'io.reac ...

  8. MySQL 的 RowNum 实现(排行榜计算用户排名)

    1. 计算用户排名最高效的方法 例如:通过用户分享个数排名,那么自己的排名就是:比自己分享数多的用户个数 + 1 ' and `count` > '自己分享个数' 缺点:当多个用户分享个数相同的 ...

  9. 「NOIP 2017」列队

    题目大意:给定一个 $n times m$ 的方阵,初始时第 $i$ 行第 $j$ 列的人的编号为 $(i-1) times m + j$,$q$ 次给出 $x,y$,让第 $x$ 行 $y$ 列的人 ...

  10. 用RecyclerView做一个小清新的Gallery效果 - Ryan Lee的博客

    一.简介 RecyclerView现在已经是越来越强大,且不说已经被大家用到滚瓜烂熟的代替ListView的基础功能,现在RecyclerView还可以取代ViewPager实现Banner效果,当然 ...