一、一元多项式的加法与乘法运算

1. 多项式的表示

(1) 数据结构选型

  • 重点在于如何表示非零项
数组 链表
优点 编程简单,调试容易 可以动态添加节点
缺点 需要事先确定数组大小 MaxSize 编程复杂,调试困难
  • 结合本例,最好的实现方法是:动态数组
    而下面将会通过链表实现

(2) 数据结构设计

struct PolyNode {int coef;           // 表示项的系数int expon;         // 表示项的指数Polynomial link;   // 指向下一个结点
};
typedef struct PolyNode *Polynomial;

(3) 程序框架搭建

int main(void) {Polynomial P1, P2, PP, PS;/* 读入多项式1 */P1 = ReadPoly();/* 读入多项式2 */  P2 = ReadPoly();/* 乘法运算并输出 */PP = Mult(P1, P2);PrintPoly(PP);/* 加法运算并输出 */PS = Add(P1, P2);PrintPoly(PS);return 0;
}
  • 需要设计的函数

    • 构造新结点(多项式新的一项)
    • 读一个多项式
    • 两多项式相乘
    • 两多项式相加
    • 多项式输出

(4) 读入多项式

  • 方法1:Rear的初值为NULL

    • 先判断Rear的值。
      若为NULL,则用malloc申请一个存储空间;
      若不为NULL,则直接在最后一项的后面添加新的一项
  • 方法2:Rear指向一个空节点

下面采用方法2

/* 功能:设置多项式(读入多项式)* 输入:void* 输出:Polynomial        P       设置的多项式的首地址*/
Polynomial ReadPoly() {Polynomial P, Rear, t;int N, c, e;/* 设置多项式的个数 N */scanf("%d", &N);/* 创建临时空结点 */P = (Polynomial)malloc(sizeof( struct PolyNode));P->link = NULL;Rear = P;                     // 更新结果多项式最后一项的地址/* 设置多项式中的各项 */while (N--) {scanf("%d %d", &c, &e);      // 第一个参数是项的系数,第二个参数是项的指数Attach(c, e, &Rear);     // 构造新结点,并加到 Rear 指向的结点(结果多项式的最后一项)的后面} /* 多项式各项创建好后,删除临时空结点 */t = P;                          // 用于空间释放P = P->link;                   // 删除临时空结点后,P 指向结果多项式第一项的首地址free(t);                     // 释放临时空结点return P;                     // 添加的新结点的首地址
}

(5) 构造新结点

/* 功能:构造新结点,并加到 Rear 指向的结点(结果多项式的最后一项)的后面* 输入:int         c           新的一项的系数 *        int        e           新的一项的指数*         Polynomial *pRear      指向结果多项式的最后一项。采用指针的指针,使对应的数据可以在自定义函数中改变(自定义函数是值传递)* 输出:void*/
void Attach(int c, int e, Polynomial *pRear) {Polynomial P;P = (Polynomial)malloc(sizeof( struct PolyNode));P->coef = c;               // 为新的一项添加系数P->expon = e;               // 为新的一项添加指数P->link = NULL;             // 新的一项将位于结果多项式的末尾,后面没有其他项(*pRear)->link = P;            // 在目前结果多项式最后一项的后面,添加新的一项*pRear = P;                    // 添加新的一项完成后,更新结果多项式最后一项的地址
}

(6) 两个多项式相加

/* 功能:两个多项式相加* 输入:Polynomial   P1      *        Polynomial     P2      * 输出:Polynomial*/
Polynomial Add(Polynomial P1, Polynomial P2) {Polynomial t1, t2, Rear, P, t;t1 = P1;t2 = P2;/* 创建临时头结点(此节点没有系数和指数),利于后续操作。整个函数执行完后,要释放该临时头结点 */P = (Polynomial)malloc(sizeof (struct PolyNode));P->link = NULL;Rear = P;/* 在循环中实现两个多项式相加。若其中一个多项式遍历完毕,则退出循环,进行下一个操作 */while (t1 && t2) {  // t1 与 t2 都是非空的结点,进入下面操作switch (Compare(t1->expon, t2->expon)) {  /* Compare 是自定义函数,用于判断前后两个系数大小若 t1 指向的多项式系数大,则返回 1若 t1 指向的多项式系数小,则返回 -1若两个多项式系数相等,则返回 0             */case 1: {Attach(t1->coef, t1->expon, &Rear);    // 将 t1 指向的多项式项,复制到结果多项式中 Rear 指向的项的后面t1 = t1->link;                     // 复制完成,P1后移break;}case 2: {Attach(t2->coef, t2->expon, &Rear);    t2 = t2->link;                      break;}case 0: {sum = t1->coef + t2->coef;          // 同类项系数相加if (sum) {                            // 若同类项系数相加的结果非0,即相加结果为非零项Attach(sum, t1->expon, &Rear);  // 将相加结果形成新结点,并加到结果多项式中 Rear 指向的项后面}t1 = t1->link;                       // t1 后移t2 = t2->link;break;}}}/* 将未遍历完的另一个多项式的所有项一次复制到结果多项式中 Rear 指向的项后面 */while (t1) {                                    // t2 指向的多项式处理完毕,t1 指向的多项式还有残余项Attach(t1->coef, t1->expon, &Rear);}while (t2) {                                    // t1 指向的多项式处理完毕,t2 指向的多项式还有残余项Attach(t2->coef, t2->expon, &Rear);}    /* 多项式各项创建好后,删除临时头结点 */t = P;                           // 用于空间释放P = P->link;                   // 删除临时空结点后,P 指向结果多项式第一项的首地址free(t);                     // 释放临时空结点return P;                     // 添加的新结点的首地址
}

(6) 两个多项式相乘

  • 方法

    • 方法1:将乘法运算转换为加法运算,即将 P1 当前项 (ci, ei)P2 多项式中的每一项,再加到结果多项式里。
    /* P1 当前项 (ci, ei) 乘 P2 多项式中的每一项 */
    t1 = P1;
    t2 = P2;// 创建空结点
    P = (Polynomial)malloc(sizeof( struct PolyNode));
    P->link = NULL;
    Rear = P;// 两个多项式相乘
    while (t2) {Attach(t1->coef * t2->coef, t1->expon + t2->expon, &Rear);t2 = t2->link
    }
    
    • 方法2:将 P1 当前项 (c1i, e1i)P2 当前项 (c2i, e2i) ,并插入到结果多项式中。问题的关键是找到正确的插入位置
    /* 功能:将两个多项式相乘* 输入:Polynomial    P1      指向第一个多项式*        Polynomial     P2      指向第二个多项式* 输出:Polynomial      P       结果多项式的第一项*/
    Polynomial Mult(Polynomial P1, Polynomial P2) {Polynomial P, Rear, t1, t2, t;int c, e;if (!P1 || !P2) { // 若P1与P2指向的多项式中至少有一个是空的return NULL;  // 退出本函数}t1 = P1; t2 = P2;P = (Polynomial)malloc(sizeof( struct PolyNode));    // 创建临时头结点P->link = NULL;Rear = P;while (t2) { // P1的第一项乘以P2的每一项,得到PAttach(t1->coef * t2->coef, t1->expon + t2->expon, &Rear); // 将乘积结果的每一项插到Rear指向的结果多项式的最后一项的后面t2 = t2->link;}t1 = t1->link;while (t1) {t2 = P2;Rear = P;                      // Rear指向结果多项式的第一项while (t2) {                  // 两个多项式中各项对应相乘e = t1->expon + t2->expon;   // 计算当前的结果项c = t1->coef * t2->coef;while (Rear->link && Rear->link->expon > e) { // 若结果多项式的Rear的下一项存在,且系数大于当前的乘积结果的系数Rear = Rear->link;       // Rear继续后移}// Rear下一项的系数小于等于乘积结果的系数if (Rear->link && Rear->link->expon == e) { // 若结果多项式的Rear下一项的系数等于当前乘积结果的系数,则这两项相加if (Rear->link->coef + c) {              // 系数相加不等于零,则更新结果中的项的系数Rear->link->coef += c;} else {                // 若系数相加等于零,则删除结果多项式中Rear后面的一项t = Rear->link;Rear->link = t->link;free(t);}} else {                   /* 若结果多项式的Rear下一项的系数小于当前乘积结果的系数,则将乘积结果插入到Rear的下一项,最终使乘积结果成为结果多项式的一项 */// 创建新结点t = (Polynomial)malloc(sizeof( struct PolyNode));t->coef = c;t->expon = e;t->link = Rear->link; // 新项的下一项是结果多项式中Rear的下一项Rear->link = t;         // 结果多项式中Rear的下一项是新项Rear = Rear->link;      // Rear移向下一项}           t2 = t2->link;}t1 = t1->link;}// 删掉临时头结点t2 = P;P = P->link;free(t2);return P;
    }
    

(7) 输出多项式

/* 功能:输出多项式* 输入:Polynomial     P       要输出的多项式的项   * 输出:* 注意:打印格式为:系数1 指数1 系数2 指数2 ……*/
void PrintPoly(Polynomial P) {int flag = 0;            // 用于调整输出格式if (!P) {                // 若多项式为空,则输出对应的格式,并退出本函数printf("0 0\n");return;}while(P) {if (!flag) {         // 若P是多项式第一项flag = 1;          // 更新flag值} else {              // 若P不是多项式第一项printf(" ");     // 先打印空格}printf("%d %d", P->coef, P->expon);    // 打印 系数 指数P = P->link;         // 移向下一项}printf("\n");                // 输出完多项式的各项后,换行
}

二、逆转链表(Reversing Linked List)

将一个单向链表的前 kkk 个结点倒转顺序,与其余结点组成新链表,输出这个新链表

1. 单链表的逆转

原链表如下

插入临时头结点,便于操作

初始化指针 newoldtmpnew 指向逆转后的链表头结点,old 指向逆转前的链表头结点 ,tmp 指向逆转前的链表第二个结点

让第二个结点指向第一个结点

三个指针均往后移一个结点

指针 old 对应结点的下一个结点是 new 对应的结点

重复最近两次步骤,重复次数是 k 步,下图是结束重复之后的状态

修改指针指向,临时头结点的下一个是 new 对应的结点,第一个结点的下一个是 old 对应的结点

/* 功能:逆转单链表* 输入:Ptr    head        包含临时头结点的单链表的首地址*         int    k           逆转前的链表中,前k个结点需要逆转* 输出:Ptr new         逆转后的单链表首地址* 注意:这是伪代码,只体现逻辑,不纠结具体细节*/
Ptr Reverse(Ptr head, int k) {/* 初始化new和old指针 */new = head->next;old = new->next;/* 循环操作 */int cnt = 1;while (cnt < k) {tmp = old->next;    // 初始化 tmp ,tmp 始终在 old 对应的结点的后一个结点old->next = new;  // 改变 old 周围的结点链接// new 和 old 整体往后移一个结点new = old;          old = tmp;cnt++;}head->next->next = old;  // 修改第一个结点的后面的链接return new;
}

2. 测试数据

  • 在本例中,原链表中的前 kkk 个结点需要逆转,而剩下的结点保持原顺序。
  • 边界测试
    • 有时题干会规定地址的可用范围,如0000~9999,则测试数据也需要包含此范围的临界值
    • 有时题干会设置链表总结点数满足 N=ak+bN=ak+bN=ak+b ,即这 NNN 个结点中,有 aaa 段长为 kkk 的结点集合,题干会要求在这几段中分别进行逆转,而剩下的 bbb 个结点不需要逆转。故测试数据时也要考虑这种情况
    • 题干要求 k=Nk=Nk=N ,即整个链表都需要逆转,则测试数据需要做出相应调整
    • 题干要求 k=1k=1k=1 ,即链表不需要逆转,则测试数据需要包含该情况
  • 题干会在原链表中加入多余结点,如空结点,防止考生使用顺序结构的数据结构组织算法

数据结构与算法 第二章习题课相关推荐

  1. 数据结构与算法第二章 线性表、栈、队列、数组、字符串、树、二叉树、哈希表的增删查

    03 增删查:掌握数据处理的基本操作,以不变应万变 通过前面课时的学习,相信你已经建立了利用数据结构去完成时空转移的思想.接下来,你需要在理论思想的指导下灵活使用.其实,要想灵活使用数据结构,你需要先 ...

  2. 数据结构与算法--第二章pro题解

    文章目录 ==模板== --双链表 ==模板==--循环双链表 1.双链表的基本运算 2:整数双链表的基本运算-3 3:整数双链表的基本运算-4 4:循环双链表的基本运算 模板 --双链表 struc ...

  3. 计算机操作系统原理第二章习题

    计算机操作系统原理第二章习题 1.什么是并发?什么是并行?用日常生活中的例子举例说明. 2.在操作系统中为什么要引入进程的概念?它会产生什么样的影响? 3.试说明PCB的作用具体表现在那些方面?为什么 ...

  4. 数据结构与算法 第二次实验报告堆栈队列

          数据结构与算法 第二次实验报告 姓名:许恺 学号:2014011329 班级:计算机14-1 中国石油大学(北京)计算机科学与技术系 前     言 <数据结构>是计算机及相关 ...

  5. 自动驾驶决策规划算法第二章——Apollo EM Planner实践篇

    前置学习内容:自动驾驶控制算法 [自动驾驶][零基础]基础自动驾驶控制算法笔记_免费教学录影带的博客-CSDN博客 自动驾驶决策规划第一章 自动驾驶决策规划算法第一章_免费教学录影带的博客-CSDN博 ...

  6. 用python编程、假设一年期定期利率_第二章-习题答案

    第二章习题 1 . 写一个算法(流程图和 python 程序) :输入三个数,输出其最 大者. numA=3 numB=4 numC=5 if numA <= numB: if numC pri ...

  7. python可以在多种平台运行、体现了_2020年智慧树数据结构与算法第二单元章节测试答案...

    2020年智慧树数据结构与算法第二单元章节测试答案 更多相关问题 为了寻找和选择通讯的报道对象,当你获知省教育招生考试院发布了<关于调整普通高等教育专科升本科考试录取办法的通知>后,应该熟 ...

  8. 统计学习导论:基于R应用——第二章习题

    目前在看统计学习导论:基于R应用,觉得这本书非常适合入门,打算把课后习题全部做一遍,记录在此博客中. 第二章习题 1. (a) 当样本量n非常大,预测变量数p很小时,这样容易欠拟合,所以一个光滑度更高 ...

  9. java第二章选择题_Java第二章习题讲解(2)

    第二章习题讲解(1) 3.阅读或调试程序 (1) 上机运行下列程序,注意观察输出的结果.Java public class E{ public static void main(String args ...

  10. Matlab第二章选择题填空题,matlab及其在大学物理中的应用第二章习题答案.doc

    matlab及其在大学物理中的应用第二章习题答案.doc MATLAB及其在大学物理中的应用第二章习题答案作者荆楚理工吴世华21试求下列极限(1)(2)XX193LIM523LIMXXX ...

最新文章

  1. 一文速览机器学习的类别(Python代码)
  2. 统计学习方法第七章作业:SVM非线性支持向量机之SMO序列最小优化算法代码实现
  3. 河北计算机科学与技术研究生,2021年河北工业大学计算机科学与技术(081200)硕士研究生招生信息_考研招生计划和招生人数 - 学途吧...
  4. BZOJ3144: [Hnoi2013]切糕
  5. 原码一位乘法器设计_数字IC校招基础知识点复习(七)——超前进位加法器、Wallace树、Booth乘法器...
  6. php获取指定日期的万年历,分享3个php获取日历的函数
  7. 用python打印九九乘法表while_利用Python循环(包括whilefor)各种打印九九乘法表的实例...
  8. 为何学这么多技术,却做不好Coder!
  9. js版in_array函数
  10. html网页div是什么意思,HTML网页中div是什么意思?
  11. CodeWisdom软件供应链系列学术报告:第2期
  12. CS_2022_01
  13. 数论概论 第三章 勾股数组与单位圆
  14. python整数除法保留两位小数
  15. uniapp根据定位城市获取对应的天气
  16. 新冷战、通货膨胀与2009年亚洲金融危机爆发 (转)
  17. ASP源码:马克斯4.0内核的DM456动漫电影网站整站源码
  18. asp php主机空间域名注册
  19. 车载摄像头贵是道理的!它的规格真的不一般!
  20. 手机淘宝短视频业务「哇哦视频」迁移上 FaaS 笔记公开

热门文章

  1. delphi之模拟按键
  2. 请问mysql优化相关
  3. STM32CubeMX官网下载方法
  4. elasticsearch kabana中创建索引
  5. ServiceStack.Redis连接阿里云redis服务时使用连接池出现的问题
  6. Jsoncpp 使用方法大全
  7. 完全掌握AS中点(.)语法的应用
  8. SNOI2017 礼物
  9. 【转载】关于.NET下开源及商业图像处理(PSD)组件
  10. 如何优雅的编写Objective-C语言?