一元多项式的相乘操作(链表)

一元多项式的乘法运算如何实现,要求多项式采用链表存储结构。

目录

基本思路:

添加条件的分类:

multiple()源代码:

detach()源代码:

处理结果:


基本思路:

        本篇博客不知觉间已经拖了好久好久了,接上一篇博客:一元多项式的相加和相减操作,就让我继续为各位讲解一下一元多项式的相乘操作。

        为了实现相乘操作,最简单且有效的办法是先用一个多项式(后文称为多项式A)的每个单项式与另外一个多项式(后文称为多项式B)的首个多项式分别相乘,建立代表结果的多项式初始多项式(也可能是单项式,这里可以不予讨论,结果并不会因为初始的结果是单项式就变得不正确,故统一认为是多项式)。然后,如果多项式B有第二项,那么将它的第二项再次分别与多项式A的各项相乘,在每一次相乘后将得到的结果单项式加入到初始多项式中,不断地更新得到的储存结果的多项式,该过程持续到多项式B的最后一项。

        在有了以上的基本思路后,我们剩下要讨论的点就很清晰明确了:该如何实现向初始多项式中添加单项式的操作呢?或者,应当把问题更明确地说为:如何确定新得到的单项式加入多项式某处的条件?

        初始多项式可能要为存储这个新的单项式而开辟一个新的位置,原因是多项式中没有和这个新的单项式的指数相同的单项式,否则就不用开辟,直接将这个新单项式与这个多项式里面对应的单项式相加后将结果存入多项式中的单项式即可,而这也可能导致一个问题:两个单项式相加后的结果的系数可能为 0 ,对于这样的情况,先不讨论,在本篇博客稍后的部分再进行讨论

对于以上过程,以a(x)=x^2-x+2与b(x)=x+1为例:

这是两个多项式的结构图示,将多项式b(x)的首项与多项式a(x)的各项分别相乘得到初始多项式c(x),其图示为:

 然后,由于b(x)有第二项,我们用b(x)的第二项再次与a(x)的各项相乘,得到第一个单项式(x^2*1):

初始多项式中有指数为2的单项式,故一个新的多项式为:

 可以看到,指数为2的这一项的系数变为0了,再将第二个单项式(-x*1)即

 放入多项式中,多项式中有指数为1的单项式,故多项式变为:

 第三个单项式(2*1):

 多项式中没有指数为0的单项式,其单项式指数最小为1,故将该单项式连接在多项式最后一项的后面:

 至于list3中的node2如何去掉,后文会介绍方法。

添加条件的分类:

        现在就让我们细分一下向初始多项式添加单项式的条件,在这之前,我们将得到的单项式存入被称为temp的结点中。在我们得到初始的多项式时,将其存入list4中,再用一个搜索指针temp4指向list4中的结点,temp4的初值为list4中的首结点的地址,在每一轮搜索后都要为其重新赋该地址值

        可以向初始的list4或是正在变化的list4的哪些地方添加这个单项式的值呢?分为三类:

1、链表的结点处

2、链表的结点间

3、链表的末尾

对于第1种情况,这是很合理的,但并不是总能出现这种情况,其成立的条件是在链表中有单项式与将被添加的单项式具有相同指数;第2种情况的出现则是因为在链表中刚好有相邻两个结点的指数分别大于和小于将被添加的单项式的指数的;第3种情况,原因在于链表的所有结点代表的单项式的指数均大于将被添加的单项式的指数,那么该结点就只能连接到链表末尾了。这三种情况产生的前置条件均是建立在多项式是按照降幂顺序排列的基础上的。

        上述的条件大致可以转化成这样的结构:

//代码清单1
//将被添加的单项式被存储在temp指向的内存区域中
while(1)
{if (temp->exp < temp4->exp){//判断temp4的下一个结点是否为空,即判断搜索指针temp4是否到达了list4的最后一个结点//若是,将temp连接到list4末尾,然后结束while循环,对应上述第3种情况//若不是,使得搜索指针temp4指向list4的下一个结点}else if (temp->exp > temp4->exp){//将temp指向的结点连接在temp4指向的结点以及该结点的前一个结点//之间,然后结束while循环,对应上述第2种情况}else{//将temp4、temp代表的单项式相加后的结果存入temp4中,然后结束//while循环,对应上述第1种情况}
}

multiple()源代码:

//代码清单2
void multiple(poly *head1, poly *head2)
{//将head1和head2指向的链表代表的多项式相乘后的结果存储在head4指向的list4中poly *head4 = (poly*)malloc(sizeof(poly));//temp4和temp_ptr用来建立初始链表	poly *temp4 = head4;poly *temp4_ptr = NULL;//temp1和temp2分别用作遍历list1和list2过程中的搜索指针poly *temp1 = head1;poly *temp2 = head2;//temp指向代表存储temp1、temp2代表的单项式相乘结果的结点,只是暂时储存poly *temp = (poly*)malloc(sizeof(poly));//pre代表temp4指向结点的前一个结点(指的是在该代码清单//第37行开始的while循环中),在处理第2种情况时会有用处poly *pre = head4;while (temp1 != NULL){temp4->sign = temp1->sign != temp2->sign ? '-' : '+';temp4->coef = temp1->coef*temp2->coef;temp4->exp = temp1->exp + temp2->exp;temp4->alph = head1->alph;temp4_ptr = temp4;temp4 = (poly*)malloc(sizeof(poly));temp4_ptr->next = temp4;temp1 = temp1->next;}temp4_ptr->next = NULL;free(temp4);temp4 = NULL;temp1 = head1;temp2 = head2->next;temp4 = head4;while (temp2 != NULL){while (temp1 != NULL){temp->sign = temp1->sign != temp2->sign ? '-' : '+';temp->coef = temp1->coef*temp2->coef;temp->alph = head1->alph;temp->exp = temp1->exp + temp2->exp;while (1){if (temp->exp < temp4->exp){if (temp4->next == NULL){temp4->next = temp;temp->next = NULL;temp = (poly*)malloc(sizeof(poly));break;}pre = temp4;temp4 = temp4->next;}else if (temp->exp > temp4->exp){pre->next = temp;temp->next = temp4;temp = (poly*)malloc(sizeof(poly));break;}else{temp->coef = temp->sign == '+' ? temp->coef : -temp->coef;temp4->coef = temp4->sign == '+' ? temp4->coef : -temp4->coef;temp4->coef = temp->coef + temp4->coef;temp4->sign = temp4->coef > 0 ? '+' : '-';temp4->coef = abs(temp4->coef);break;}}temp1 = temp1->next;}temp2 = temp2->next;temp1 = head1;temp4 = head4;}free(temp);temp = NULL;output(head4);
}

先不着急讲解,我们可以测试一下这个代码:

        结果是符合我们预期的,美中不足的是c(x)中的"-0x"不太美观哈,但这不要紧,后面我们将想办法去掉,由于这种情况的产生源于多项式相乘过程中指数相同的两项的系数互为相反数,也许你会想到在执行第1种情况的代码中利用pre指针将系数为0的这一项移除,但这并不是更好的方法,想一想,如果你将两个多项式的值都设置为多个系数为0的单项式的和,结果会使得list4一直重复去除系数为0的单项式,而最后整个结果也为0,接下来是不是要将list4置空?这样会使得list4代表的结果即0无法被打印出来,所以我觉得最好的方法是建立一个函数,通过这种方法会使得我们的思路简化很多。

        代码清单2第18至32行用于建立初始链表,而由于我们采用的建立初始链表list4的方法是将list2代表的多项式的首项与list1代表的多项式的每一项相乘得到,所以在34行开始让temp1重新指向list1的首结点,让temp2指向list2的首结点的后一个结点(可能为NULL,不要紧),让temp4指向list4的首结点。第37和39行开始的while循环注意次序,第76行对应内层的while循环,第78至80行间的代码则对应外层的。第41至44行的代码用于建立temp指向的结点。第45至75行的循环设置为类似死循环的循环结构是因为有可以结束这个循环的条件,也就是说最终能把temp指向的结点成功填入list4中

detach()源代码:

//代码清单3
poly *detach(poly *head)
{poly *temp = NULL;poly *pre = head;while (head->coef == 0){if (head->next == NULL)break;head = head->next;free(pre);pre = head;}temp = head->next;pre = head;while (temp != NULL){while (temp->coef == 0){temp = temp->next;free(pre->next);if (temp != NULL)pre->next = temp;else{pre->next = NULL;return head;}}pre = temp;temp = temp->next;}return head;
}

        如何去除存储相乘结果的链表中的代表系数为0的单项式的结点呢?为此,detach()函数被写了出来。我的想法是这样的:如果list4(假设有多个结点)中前几个结点代表系数为零的单项式,那么我们在将这几个结点从list4中去除后,选择list4中的第一个非零结点作为首结点,以此为起点,继续用搜索指针一步步后移将之后的零结点去除,直到搜索指针指向NULL,即整条链表被遍历完全

        代码清单3第6至13行的代码,就像我前面提到的,它的主要作用是去除list4中的前几个零结点,如果有的话,没有的话自然就不执行,例如下图:

在将node1删除后,node1后续几个结点依次前移,形成新的list4。然后就是第8至9行的if判断结构,它是十分重要的,体现在以下情况:

1、list4只有一个结点,list4代表着一个系数为0的单项式

2、list4具有多个结点,但每个结点代表的系数均为0,list4代表着一个零多项式

所以,在符合两种情况之一时,这个判断结构保证能够为list4保留一个结点。那么保留的结点是list4中的哪个结点呢?对于第一种情况,不必多说;对于第二种情况,则会将list4中的最后一个结点保留下来。第14行代码中temp的值可能为NULL,原因就在于这两种情况 ,这样的话也就不会执行第16至32行的while循环了。说到第16至32行的while循环,它就是用来处理list4中已经确定的非零结点后面的零结点的,例如下图:

以node1为起点,历经node2,发现后续几个结点都是零结点,直到node5,那么这个while循环会将node3、node4删除,node5、node6会变成新的node3、node4。当然,list4的末尾几个结点也有可能是零结点,处理的方法是一样的。

处理结果:

        既然detach()函数写好了,我们将它添入multiple()函数的第83行和第84行语句的中间,执行一下,运行结果为:

结果是很OK的。


欢迎指正我的上一篇博客:一元多项式的相加和相减操作(链表)

我的下一篇博客:待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/143307.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构一元多项式的相加-单链表实现

实验内容&#xff1a;把任意给定的两个一元多项式P(x) ,Q(x) 输入计算机&#xff0c;计算它们的和并输出计算结果。 一元多项式可以用单链表表示&#xff0c;结点结构图示如下&#xff1a; coef expnext 首先分析一下这个过程是如何实现的 该算法需要求A与B两个一元多项式的和&…

一元多项式加减乘实现c/c++

一、实验题目&#xff1a; 一元多项式简单的计算器 1.主要功能&#xff1a; (1)输入并建立多项式&#xff1b; (2)输出多项式&#xff1b; (3)两个多项式相加&#xff0c;建立并输出和多项式&#xff1b; (4)两个多项式相减&#xff0c;建立并输出差多项式。 (5)算法的时…

一元多项式的加法

一元多项式的加法 问题描述&#xff1a;一元多项式的加法 &#xff08;1&#xff09; 编程实现一元多项式的加法。 &#xff08;2&#xff09; 编写一个测试主函数。 分析&#xff1a; 对于任意一元多项式 可以抽象为一个由“系数—指数”对构成的线性表&#xff0c;且线性表中…

一元多项式求导

问题描述&#xff1a; 设计函数求一元多项式的导数。&#xff08;注&#xff1a;x​n​​&#xff08;n为整数&#xff09;的一阶导数为nx​n−1​​。&#xff09; #include<cstdio> int main() {int a[100000];int b[100000];int n,m;char c;//判断结束的条件scanf(&q…

一元多项式课设

代码详见 目录 一、实习任务........................................................................................... - 1 - 1.问题描述&#xff1a;.................................................................................... - 1 - 2.小组分工.........…

数据结构:一元多项式及其基本运算

1、实现方式&#xff1a;可采用线性表的顺序存储结构&#xff0c;但是当多项式的每个项的指数差别很大时&#xff0c;会浪费很多存储空间。所以采用链式存储方式表示&#xff0c;每一项可以表示成一个结点&#xff0c;结点的结构由存放系数的coef域&#xff0c;存放指数的expn域…

一元多项式计算

目录 题目的内容及要求--------------------------------------------2需求分析-------------------------------------------------------2概要设计-------------------------------------------------------2 1、存储结构------------------------------------------------…

【数据结构】一元多项式的表示及相加

文章目录 ⭐️写在前面的话⭐️一元多项式的表示及相加初始化0_1、初始化链表0_2_1、头插法插入多项式的项(没有相同项)0_2_2、将要插入的相同&#xff0c;链表中有相同项&#xff0c;对应系数相加0_3、从链表中查找是否有相同的指数项0_4、对已经创建好的一元多项式按指数大小…

数据结构(严蔚敏)【一元多项式的运算】【C语言】

1、一元多项式的运算&#xff1a;实现两个多项式加、减乘运算 设计内容&#xff1a; 用顺序存储结构实现一元多项式的加法、减法和乘法。具体要求为&#xff1a;用五个函数分别实现一元多项式的创建、输出、加法、减法和乘法&#xff1b; 设计思路&#xff1a; 将顺序表数组…

算法竞赛入门【码蹄集进阶塔335题】(MT2151-2175)

算法竞赛入门【码蹄集进阶塔335题】(MT2151-2175&#xff09; 文章目录 算法竞赛入门【码蹄集进阶塔335题】(MT2151-2175&#xff09;前言为什么突然想学算法了&#xff1f;为什么选择码蹄集作为刷题软件&#xff1f; 目录1. MT2151 权值计算2. MT2152 黑客小码哥3. MT2153 来给…

Linux基础之LVM卷管理

LVM LVM是 Logical Volume Manager&#xff08;逻辑卷管理&#xff09;的简写&#xff0c;它是Linux环境下对磁盘分区进行管理的一种机制。Linux用户安装Linux操作系统时遇到的一个常见的难以决定的问题就是如何正确地评估各分区大小&#xff0c;以分配合适的硬盘空间。普通的…

linux lvcreate,LFCS:如何使用vgcreate,lvcreate和lvextend命令管理和创建LVM - 第11部分...

因为在LFCS考试要求有效的二月变化 2&#xff0c;2016年 &#xff0c;我们增加了必要的专题到LFCS系列发表在这里。 为了准备这场考试&#xff0c;你是高度鼓励使用联邦经济竞争法系列为好。 LFCS&#xff1a;管理LVM和创建LVM分区 - 第11部分 安装Linux系统时最重要的决定之一…

lvm 制作

壹&#xff1a; 创建LVM 逻辑卷 1&#xff0c;将物理盘格式为pv卷&#xff08;物理卷&#xff09;&#xff0c;使用pvcreate 命令 pvcreate /dev/sdc 或则是 pvcreate /dev/sdc /dev/sdb pvdisplay 或pvs 命令查看 PV 物理卷得创建情况 2,创建卷组 VG 通过vgcreate 命令,将pv加…

lvcreate 常用命令举例

http://linux.cn/article-5117-1.html4 个 lvcreate 常用命令举例 2015-3-25 15:09| 查看: 2752| 评论: 3| 收藏: 3| 分享: 10 原文&#xff1a;http://www.ehowstuff.com/4-lvcreate-command-examples-on-linux/作者&#xff1a; skytech译文&#xff1a;LCTT https://linux.…

49.逻辑卷管理4,逻辑卷管理详解,lvscan,lvcreate,lvdisplay,lvextend,lvreduce,lvremove,lvresize,lvchange

逻辑卷相关操作 可以把逻辑卷想象成分区&#xff0c;那么这个逻辑卷当然也需要被格式化和挂载。另外&#xff0c;逻辑卷也是可以动态调整大小的&#xff0c;而且数据不会丟失&#xff0c;也不用卸载逻辑卷。 常用的命令有 lvscan Lvcreate Lvdisplay lvextend lvreduce Lvremov…

oppo手机删除计算机怎样恢复,【数据恢复篇】oppo手机删掉的照片怎么恢复

原标题&#xff1a;【数据恢复篇】oppo手机删掉的照片怎么恢复 手机删掉的照片可以恢复吗&#xff1f;oppo手机删掉的照片怎么恢复&#xff1f;很多人会奇怪oppo手机删掉的照片还能恢复吗&#xff1f;现在科技技术的提高&#xff0c;照片能够被恢复也是很简单的。像我们所知道的…

苹果手机照片误删恢复的方法

苹果手机照片误删恢复的方法&#xff1f;苹果手机相册里都有一个【最近删除】相册&#xff0c;为了恢复我们手机里误删的照片&#xff0c;我们首先可以打开相册&#xff0c;然后找里面的最近删除的相簿&#xff0c;看看里面有没有自己误删的照片&#xff0c;如果有的话&#xf…

android sd卡数据恢复软件下载,手机SD卡内存卡数据恢复软件

手机SD卡内存卡数据恢复软件免费版是一款专门解决内存卡等存储介质数据丢失问题的恢复软件&#xff0c;支持各个型号的SD卡、内存卡及U盘的删除恢复、格式化恢复等。 手机SD卡内存卡数据恢复软件是一款简单易用功能强大的数据恢复软件。该软件有针对性的对各类内存卡进行数据恢…

android 恢复照片误删,安卓手机数据恢复:红米手机照片误删怎么恢复

原标题&#xff1a;安卓手机数据恢复&#xff1a;红米手机照片误删怎么恢复 红米手机误删照片怎么恢复&#xff1f;小编的也爷爷使用的是红米手机&#xff0c;有一天跟我说“他误删了手机上的很多张照片&#xff0c;还一直抱怨自己眼花乱删东西”。小编就赶紧安慰爷爷还说会帮他…

android删除sd卡照片恢复,安卓手机照片误删怎么恢复

现如今国内大多的人都拥有一部智能手机&#xff0c;使用手机拍摄照片记录生活中的美好也成为了一种普遍流行的行为。当我们用手机照片记录身边点滴后&#xff0c;经过时间的打磨&#xff0c;我们也需要整理这些照片&#xff0c;误删照片随之成为一个严峻的问题&#xff0c;手机…