稀疏一元多项式运算器实验报告附源程序.docx
《稀疏一元多项式运算器实验报告附源程序.docx》由会员分享,可在线阅读,更多相关《稀疏一元多项式运算器实验报告附源程序.docx(14页珍藏版)》请在冰豆网上搜索。
稀疏一元多项式运算器实验报告附源程序
信息学院12级杨征元PB稀疏一元多项式运算器
问题描述:
完成一元稀疏多项式运算器,完成多项式创建,显示,复制,求和,求差,求值,销毁,清空,修改,n阶微分,不定积分,定积分操作。
函数功能描述如下:
稀疏一元多项式运算器
0.退出退出
1.创建多项式创建并打印
2.显示多项式打印
3.复制多项式复制多项式a至空域b,非空报错
4.求和输入abc位置,c=a+b
5.求差输入abc位置,c=a-b
6.求值输入位置,doublex,输出doubleresult
7.销毁多项式销毁,使p[i]为NULL
8.清空多项式清空保留头指针,输出为0
9.修改多项式选择插入,删除,修改(删了再插)
阶微分输入微分位置,阶数,结果存放于原位置
11.不定微分输入积分位置,不定积分,常数C取0
12.定微分输入积分位置,上下限值,输出定积分结果
算法描述:
通过主菜单调用函数完成各项功能,函数描述见程序结构描述部分。
数据结构描述:
多项式每一项结点定义如下:
typedefstructlnode{
doublecoef;
intexp;
structlnode*next;
}lnode,*linklist;
包含指向下一结点指针linklistnext,存储系数的数据单元doublecoef,存储指数的数据单元intexp;结点名lnode,指向结点指针linklist。
每一个多项式由头指针引出,头指针数组lnode*p[N]。
每一个单元存储一多项式头指针。
当多项式不存在,p[i]=NULL;多项式为空,p[i]->next=NULL,即只存在头指针。
操作函数见程序结构描述部分。
程序结构描述:
函数包括创建结点函数,有序插入函数,打印函数,创建多项式函数,多项式清空函数,多项式销毁函数,求值函数,求和函数,求差函数,复制函数,删除结点函数,修改函数,n阶微分函数,不定积分函数。
对函数原型,功能,借口逐一描述如下:
创建结点函数
函数原型:
linklistmakenode(doublecoef,intexp)
输入double型系数项,int型指数项,创建lnode结点,返回指向结点的linklist指针。
功能:
创建新结点,在复制函数以及输入系数指数插入结点时(修改多项式)
调用。
有序插入函数
函数原型:
voidinsert(linklistphead,linklisthead)
输入插入结点指针phead以及多项式头指针head,无返回值
功能:
新结点phead有序插入头结点为head的多项式内(按指数项降序排列),在创建,复制,修改函数中调用。
打印函数
函数原型:
voidprintlinklist(linklistphead)
输入待打印多项式头指针phead,无返回值
分别打印系数项和指数项,打印系数项是使用%g输入取消无效0,通过特殊情况讨论(如exp=0,exp=1,首项的加号等情况),使多项式输出符合书写习惯。
功能:
打印多项式
创建多项式
函数原型:
linklistcreatlist()
返回创建多项式头指针,调用时先在主函数中输入该多项式头指针在头指针数组中位置。
实现:
先若该位置无多项式,申请头结点,之后新建数据结点,有序插入头结点对应多项式。
清空多项式
函数原型:
voidlinklistclear(linklisthead)
输入待清空多项式头结点,无返回值,将p[i]仅保留头结点。
实现:
用前后两指针,遍历多项式并逐一删去结点,最后将头指针的next域置NULL。
销毁多项式
函数原型:
voidlinklistdestroy(linklist&head)
输入待销毁多项式头结点,无返回值,将p[i]置NULL
实现方法类似清空,删去包括head在内结点。
多项式求值
函数原型:
doublelinklistvalue(linklisthead,doublex)
输入待求多项式头结点,变量x值doublex,返回double型结果
实现:
通过exp求每一项权重,与系数coef相乘,最后累加所有结果。
多项式求和
函数原型:
voidlinklistadd(linklistahead,linklistbhead,linklist&chead)
输入相加两多项式a,b头指针以及输出位置c,无返回值
实现:
通过pa,pb遍历a,b,新建c结点对比当前位置a,bexp大小,分别做对应赋值,之后将c结点插入c多项式中(*当c新结点系数为0时不进行插入)
多项式求差
函数原型:
voidlinklistsub(linklistahead,linklistbhead,linklist&chead)
输入相减两多项式a,b头指针以及输出位置c,无返回值
实现完全与求和相同
多项式复制
函数原型:
linklistlinklistcopy(linklista)
输入待复制多项式头指针linklista,输出复制结果指针linklist。
遍历多项式a,读取每一结点coef,exp值,调用makenode函数创建新结点,插入多项式b,返回b头指针head。
删除多项式中一节点
函数原型:
intlinklistdelete(linklisthead,intm)
输入待删除多项式头指针linklisthead,待删除项指数值intm,成功返回1,反之-1
删除head中一指数为m项,修改函数中调用
实现:
遍历多项式,若指数项系数为m,free(p)
修改多项式
函数原型:
voidlinklistmodify(linklisthead)
输入待修改多项式头指针linklisthead,无返回值
调用函数时输入1,2,3选择插入结点,删除结点,修改结点操作(删除后插入),分别调用delete函数及insert函数实现。
微分
函数原型:
voidlinklistdiff(linklist&head)
输入待微分多项式头指针linklisthead,按照求导规则逐项修改系数,指数,并对原常数项结点进行删除操作。
实现N阶微分是在主函数中n次调用即可。
不定积分
函数原型:
voiditeintegral(linklisthead)
输入多项式头指针linklisthead,无返回值
按多项式积分规则逐项修改系数,指数,对不定积分中C取0。
实现定积分是同时调用不定积分函数与求值函数即可。
算法时空分析:
无复杂嵌套,均一次遍历即可,对多项式操作复杂度均为O(N)数量级。
调试及结果分析:
选择键面:
创建多项式:
创建并打印,指数为0结束
显示多项式:
判断第一项前不输出+,指数正负1,0修改输出格式
复制多项式:
求和:
说明:
为测试一个多项式先加完的情况,选择b多项式指数项系数大于a,在未修改前因访问b->exp,而b=NULL报错。
修改分情况讨论。
求差:
求值:
销毁:
清空:
修改:
n阶微分:
验证删除常数项微分功能,选择该实验数据
不定积分:
定积分:
遍历每个函数验证可行,一些特殊分支的测试函数不予以列出,调试时主要解决一些健壮性问题以及一些未考虑周全的方面。
实验体会和收货:
实验中大部分函数思路较为简单,但存在大量细节问题。
如打印多项式中,系数的无效0去除,打印结果与正常书写习惯的符合性;add函数中某多项式先插完的极端情况;加减函数中结果为0项的删除;主函数中输入位置i合法性检查等。
完善其在各种极端情况下的健壮性很多时候更为耗时,但却是必须的。
在写较大函数时应进行分块。
本实验完成时,我采取了完成create,print函数后逐一写运算函数的方法,尽管在单个函数调试时并未有明显障碍,但给之后调用和阅读带来极大不便,以后需要避免。
处理这类问题时,最复杂的步骤往往是确定和建立数据结构,本次完成实验的很大一部分时间花在了基础函数(create,insert,print)的完成上,而非简单的运算函数。
测试数据选择需加以仔细思考一方面是有些数据可同时测试多路,提高效率,更重要的是很多极端情况只有特定函数才能完成测试。
#include<>
#include<>
#include<>
typedefstructlnode{
doublecoef;
intexp;
structlnode*next;
}lnode,*linklist;
#defineN20
lnode*p[N]={NULL};除结点\n2.增加结点\n3.修改结点\n");
scanf("%d",&flag);
switch(flag){
case1:
{
printf("输入删除结点指数值:
");
scanf("%d",&exp);
linklistdelete(head,exp);
break;}
case2:
{
printf("输入增加结点指数值系数:
");
scanf("%d%lf",&exp,&coef);
insert(makenode(coef,exp),head);
break;}
case3:
{
printf("输入指数修改后系数:
");
scanf("%d%lf",&exp,&coef);
linklistdelete(head,exp);
insert(makenode(coef,exp),head);
break;}
}
}
voidlinklistdiff(linklist&head){
linklistp=head->next;
while(p!
=NULL){
if(p->exp==0){
linklistdelete(head,0);
break;
}
else{
p->coef*=p->exp;
p->exp-=1;
p=p->next;
}
}
}
voiditeintegral(linklisthead){
linklistp=head->next;
while(p!
=NULL){
p->exp+=1;
p->coef=p->coef/p->exp;
p=p->next;
}
}
intmain(){
intflag,i;
printf("*************************************************\n");
printf("*稀疏一元多项式运算器*\n");
printf("*0.退出*\n");建多项式*\n");示多项式*\n");制多项式*\n");和*\n");差*\n");值*\n");毁多项式*\n");空多项式*\n");改多项式*\n");定微分*\n");
printf("*12.定微分*\n");
printf("*************************************************\n");
while
(1){
printf("键入数字选择操作:
");
scanf("%d",&flag);
switch(flag){
case0:
{
printf("thanksforusing\n");
return0;}
case1:
{
printf("inputlocation:
");
scanf("%d",&i);
if(p[i-1]==NULL)
p[i-1]=creatlist();
else
printf("空间已被占用\n");
break;}
case2:
{
printf("输入显示位置:
");
scanf("%d",&i);
if(p[i-1]!
=NULL)
printlinklist(p[i-1]);
else
printf("该位置无多项式\n");
break;}
case3:
{
intj;
printf("input原位置复制位置:
");
scanf("%d%d",&i,&j);
if(p[i-1]!
=NULL&&p[j-1]==NULL)
p[j-1]=linklistcopy(p[i-1]);
else
printf("输入位置空或输出位置满");
break;}
case4:
{
intj,k;
printf("输入a,b位置,以及输出c位置:
");
scanf("%d%d%d",&i,&j,&k);
if(p[i-1]!
=NULL&&p[j-1]!
=NULL&&p[k-1]==NULL)
linklistadd(p[i-1],p[j-1],p[k-1]);
elseprintf("位置被占用或原多项式不存在\n");
break;}
case5:
{
intj,k;
printf("输入a,b位置,以及输出c位置:
");
scanf("%d%d%d",&i,&j,&k);
if(p[i-1]!
=NULL&&p[j-1]!
=NULL&&p[k-1]==NULL)
linklistsub(p[i-1],p[j-1],p[k-1]);
elseprintf("位置被占用或原多项式不存在\n");
break;}
case6:
{
printf("输入多项式位置:
");
scanf("%d",&i);
if(p[i-1]!
=NULL){
doubletempx;
printf("输入x值:
");
scanf("%lf",&tempx);
printf("结果为%g\n",linklistvalue(p[i-1],tempx));
}
else
printf("该位置无多项式\n");
break;}
case7:
{
printf("输入删除位置:
");
scanf("%d",&i);
if(p[i-1]!
=NULL)
linklistdestroy(p[i-1]);
else
printf("该位置无多项式\n");
break;}
case8:
{
printf("输入清空位置:
");
scanf("%d",&i);
if(p[i-1]!
=NULL)
linklistclear(p[i-1]);
else
printf("该位置不存在多项式\n");
break;}
case9:
{
printf("输入修改对象位置:
");
scanf("%d",&i);
if(p[i-1]!
=NULL)
linklistmodify(p[i-1]);
else
printf("对应位置为空\n");
break;}
case10:
{
printf("输入微分位置:
");
scanf("%d",&i);
printf("输入求导阶数:
");
intn,j;
scanf("%d",&n);
if(p[i-1]!
=NULL){
for(j=0;jlinklistdiff(p[i-1]);
}
else
printf("该位置无多项式\n");
break;}
case11:
{
printf("输入不定积分位置:
");
scanf("%d",&i);
if(p[i-1]!
=NULL)
iteintegral(p[i-1]);
else
printf("该位置无多项式\n");
break;}
case12:
{
printf("输入定积分位置:
");
scanf("%d",&i);
doublej1,j2;
printf("输入上下限:
");
scanf("%lf%lf",&j1,&j2);
if(p[i-1]!
=NULL){
iteintegral(p[i-1]);
printf("%g\n",linklistvalue(p[i-1],j1)-linklistvalue(p[i-1],j2));
}
else
printf("该位置无多项式\n");
break;}
}
}
}