【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的测试代码写在一起了
#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:有序多项式相乘的更多相关文章
- 第03章 AOP前奏
第03章 AOP前奏 提出问题 ●情景:数学计算器 ●要求 ①执行加减乘除运算 ②日志:在程序执行期间追踪正在发生的活动 ③验证:希望计算器只能处理正数的运算 ●常规实现 ●问题 ○代码混乱:越来越多 ...
- 第03章_基本的SELECT语句
第03章_基本的SELECT语句 1. SQL概述 1.1 SQL背景知识 1946 年,世界上第一台电脑诞生,如今,借由这台电脑发展起来的互联网已经自成江湖.在这几十年里,无数的技术.产业在这片江湖 ...
- 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 ...
- 【Weiss】【第03章】练习3.8:有序多项式求幂
[练习3.8] 编写一个程序,输入一个多项式F(X),计算出(F(X))P.你程序的时间复杂度是多少? Answer: (特例:P==0时,返回1.) 如果P是偶数,那么就递归计算((F(X))P/2 ...
- 【Weiss】【第03章】练习3.6:有序多项式相加
[练习3.6] 编写将两个多项式相加的函数.不要毁坏输入数据.用一个链表实现. 如果这两个多项式分别有M项和N项,那么你程序的时间复杂度是多少? 两个按幂次升序的多项式链表,分别维护一个指针. 幂较小 ...
- 【Weiss】【第03章】练习3.4、3.5:有序链表求交、并
[练习3.4] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∩L2的过程. [练习3.5] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∪L2的过程. 思路比较简单,测 ...
- 【Weiss】【第03章】练习3.16:删除相同元素
[练习3.16] 假设我们有一个基于数组的表A[0,1...N-1],并且我们想删除所有相同的元素. LastPosition初始值为N-1,但应该随着相同元素被删除而变得越来越小. 考虑图3-61中 ...
- 【Weiss】【第03章】增补附注
基本上每章到增补附注这里就算是结束了. 根据设想,每章的这一篇基本上会注明这一章哪些题没有做,原因是什么,如果以后打算做了也会在这里补充. 还有就是最后会把有此前诸多习题的代码和原数据结构放整理后,以 ...
- 【Weiss】【第03章】练习3.25:数组模拟队列
[练习3.25] 编写实现队列的例程,使用 a.链表 b.数组 Answer: 在这章一开头就已经写了个链表的队列例程了,所以实际上只要做b小题就可以. 数组模拟队列和链表的两点小不同是: ①.数组空 ...
随机推荐
- Ubuntu12.10下安装Python3
设置Python3.2为默认版本 ubuntu12.10下默认安装了Python2.7和Python3.2.3,并且设置了Python2.7为默认的版本,因此如果讨厌麻烦的话,可以直接将Python3 ...
- application.properties和application.yml
1.application.properties 文件和 application.yml 文件优先级: 当同时存在时,那application.yml 只是个摆设. 2.yml文件的好处,天然的树状结 ...
- CIA Hive Beacon Infrastructure复现1——使用Apache mod_rewrite实现http流量分发
0x00 前言 2017年11月9日维基解密公布一个代号为Vault8的文档,包含服务器远程控制工具Hive的源代码和开发文档.开发文档中的框架图显示Hive支持流量分发功能,若流量有效,转发至Hon ...
- mybatis 添加后获得该新增数据自动生成的 id
// useGeneratedKeys默认值为false,keyProperty的值对应的是User类中的主键字段名 // mybatis 写法如下 <insert id="inser ...
- Typescript - 变量类型
原文:TypeScript基本知识点整理 一.number let num1 : number = 20; let num2 : number = 175.5; let a1 : number = I ...
- js 原生轮播图插件
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Docker学习笔记_04 Rancher的部署安装(编排选用K8S)
原文地址:http://dbase.cc/2018/01/12/docker/04_rancher的部署安装/ 为什么要使用Rancher Rancher是一个开源的企业级容器管理平台.通过Ranch ...
- 严谨与特色并行——WSDM 2015大会见闻记
2015大会见闻记" title="严谨与特色并行--WSDM 2015大会见闻记"> 第8届ACM网络搜索与数据挖掘会议(ACM International Co ...
- linux公社大量免费的在线android资料
2011年linux数据库的android在线分享 linux公社:开源公社 本文撰写:杨凯专属频道 下载如需密码,详见博客案例:点击我去查看密码 2011年9月12日 21: ...
- 悖论当道,模式成空:汽车O2O真是死得其所?
O2O热潮的兴起似乎来得颇为蹊跷--或许是线上连接线下的模式太过空泛,具有极大的包容性,让各个行业都忍不住在其中横插一脚.在经历过最初的崛起和后来的火爆之后,最终形成目前的寒冬.究其原因,O2O并不是 ...