【练习3.6】

编写将两个多项式相加的函数。不要毁坏输入数据。用一个链表实现。

如果这两个多项式分别有M项和N项,那么你程序的时间复杂度是多少?

两个按幂次升序的多项式链表,分别维护一个指针。

幂较小者将元素的副本拷贝入节点并加入新链表,指针向后移动。

幂同样大时,将两者的系数相加后的结果加入新链表,两个多项式链表的指针共同向前移动。

其中一个多项式到达尾部时,如另一个未到达尾部,则一边后移一边将相同元素的新节点加入新链表。

时间复杂度O(M+N)。

测试代码如下:

 #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::polyplus(a, b);
cout << "\n ( " << flush;
answer.traverse();
cout << ") \n" << flush;
system("pause");
}

实现方面,首先定义了多项式类,以及必要的构造函数及运算符重载,放在poly.h头文件中

 #ifndef POLY
#define POLY
#include <iostream>
using namespace std; namespace poly
{
//练习3.6新增,多项式元素定义
class Poly
{
friend bool operator<(const Poly& poly1, const Poly& poly2);
friend bool operator==(const Poly& poly1, const Poly& poly2);
friend bool operator!=(const Poly& poly1, const Poly& poly2);
friend ostream& operator<<(ostream &os, const Poly& poly);
friend Poly operator+(const Poly& poly1, const Poly& poly2);
public:
Poly() = default;
Poly(int coe, int exp) :coefficient(coe), exponent(exp){}
private:
//多项式系数
int coefficient;
//多项式指数
int exponent;
};
//练习3.6新增,多项式元素对应操作符重载,包括<<、<、==、!=,+
bool operator<(const Poly& poly1, const Poly& poly2)
{
return poly1.exponent < poly2.exponent;
}
bool operator==(const Poly& poly1, const Poly& poly2)
{
return poly1.exponent == poly2.exponent;
}
bool operator!=(const Poly& poly1, const Poly& poly2)
{
return !(poly1 == poly2);
}
ostream& operator<<(ostream &os, const Poly& poly)
{
cout << poly.coefficient << "x^" << poly.exponent << flush;
return os;
}
Poly operator+(const Poly& poly1, const Poly& poly2)
{
if (poly1 != poly2)
throw runtime_error("Undefined operation!");
else
{
Poly answer;
answer.coefficient = poly1.coefficient + poly2.coefficient;
answer.exponent = poly1.exponent;
return answer;
}
}
}
#endif

在原链表例程中包含该头文件,并将Poly类与polyplus函数(该函数不是List的成员函数)设为友元

 #ifndef LINKLIST
#define LINKLIST
#include <iostream>
#include "poly.h"      //包含poly头文件
using namespace std;
using namespace poly; namespace linklist
{
/…………/
template <typename T> class List
{
  /…………/
//练习3.6新增,友元声明
friend List<Poly> polyplus(const List<Poly> &inorder_a, const List<Poly> &inorder_b);
friend struct Poly;
/…………/
} /…………/
}

最后是具体实现代码:

 //练习3.6新增,不覆盖原传入数据,多项式相加
List<Poly> polyplus(const List<Poly> &inorder_a, const List<Poly> &inorder_b)
{
List<Poly> answer;
Node<Poly>* pwrite = answer.front;
Node<Poly>* pread_a = inorder_a.front;
Node<Poly>* pread_b = inorder_b.front;
while (pread_a != nullptr && pread_b != nullptr)
{
//为实现升序排列,元素较小者加入新的链表,并向前移动指针
if (pread_a->data < pread_b->data)
{
answer.additem(pread_a->data, pwrite);
if (pwrite == nullptr)
pwrite = answer.front;
else
pwrite = pwrite->next;
pread_a = pread_a->next;
}
else if (pread_b->data < pread_a->data)
{
answer.additem(pread_b->data, pwrite);
if (pwrite == nullptr)
pwrite = answer.front;
else
pwrite = pwrite->next;
pread_b = pread_b->next;
}
//元素一样大时共同向前移动指针
else
{
answer.additem(pread_a->data + pread_b->data, pwrite);
if (pwrite == nullptr)
pwrite = answer.front;
else
pwrite = pwrite->next;
pread_a = pread_a->next;
pread_b = pread_b->next;
}
}
//如果其中任一链表未遍历,将剩余的元素复制入新的链表
while (pread_a != nullptr)
{
answer.additem(pread_a->data, pwrite);
if (pwrite == nullptr)
pwrite = answer.front;
else
pwrite = pwrite->next;
pread_a = pread_a->next;
}
while (pread_b != nullptr)
{
answer.additem(pread_b->data, pwrite);
if (pwrite == nullptr)
pwrite = answer.front;
else
pwrite = pwrite->next;
pread_b = pread_b->next;
}
return answer;
}

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

  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.7:有序多项式相乘

    [练习3.7] 编写一个函数将两个多项式相乘,用一个链表实现.你必须保证输出的多项式按幂次排列,并且任意幂次最多只有一项. a.给出以O(M2N2)时间求解该问题的算法. b.写一个以O(M2N)时间 ...

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

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

  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. 旅游机票类专业名词---PNR

    PNR: PNR是旅客订座记录,即Passenger Name Record的缩写,它反映了旅客的航程,航班座位占用的数量,及旅客信息.适用民航订座系统. 一个PNR由以下几项组成: 姓名组NM 航段 ...

  2. 【转载】[基础知识]【网络编程】TCP/IP

    转自http://mc.dfrobot.com.cn/forum.php?mod=viewthread&tid=27043 [基础知识][网络编程]TCP/IP iooops  胖友们楼主我又 ...

  3. Oops 的栈信息分析

    MTK MT55 F3600 平台 现象:播放MP4文件不断快退或者快进系统重启. 关键log: Kernel panic - not syncing: x_msg_q_receive(): not ...

  4. 开始使用Github

     Gather ye rosebuds while ye may 我自己也是刚开始使用github没几天,写得不好我就写自己常用的吧 2015年9月20日下午3:19更新知乎上这个答案写得好多了

  5. 探究 Go 语言 defer 语句的三种机制

    Golang 的 1.13 版本 与 1.14 版本对 defer 进行了两次优化,使得 defer 的性能开销在大部分场景下都得到大幅降低,其中到底经历了什么原理? 这是因为这两个版本对 defer ...

  6. oa办公系统快速开发工具,助力企业优化升级

    随着互联网的快速发展.信息化 IT 技术的不断进步.移动互联新技术的兴起,不管是大的集团企业还是中小型企业,纸质化的办公模式已不能满足现有需求,构建oa平台,为员工提供高效的办公环境尤其重要. 我们先 ...

  7. 从零认识 DOM (一): 对象及继承关系

    先上图为敬! 说明: 图中包括了大部分 DOM 接口及对象, 其中: 青色背景为接口, 蓝色背景为类, 灰色背景表示为 ECMAScript 中的对象 忽略了一部分对象, 包括: HTML/SVG 的 ...

  8. 我折腾的shell笔记

    目录 Mac一些常用的快捷键记录 iTerm2或者命令行相关 Mac桌面上或者某目录下操作 一些实用脚本示例 代码无提示或者其他抽风症状,清除Xcode缓存 查看当前网络ip地址 日常提交推送git代 ...

  9. Java8 新特性2——强大的Stream API

    强大的Stream API Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找.过滤和映射数据等操作.简而言之,Stream API 提供 ...

  10. idea 2018.1激活方法

    之前用的idea都是2017版本的,现在已经四月份了,对于2018年1月份的版本应该可以放心的用了. 在这里,仅提供2018版本的激活码. 至于安装步骤,这里省略一千个字...... 下面是具体的激活 ...