利用链表实现一元多项式的数学运算。如一元多项式
能够利用其系数𝑝和指数𝑒组合的方式实现链式存储。经过对线性表的基本操做,例如插入,删除,查找等能够实现一元多项式的复杂运算,好比加,减,乘,除等运算。
利用链表存储一元多项式,经过对链表的操做实现多项式的运算。
对于多项式:𝐴(𝑥) = 7 + 3𝑥 + 9𝑥 + 5𝑥,𝐵(𝑥) = 8𝑥 + 22𝑥 − 9𝑥,实现加,减,乘和微分,输出结果。
代码结构为主分形式,主函数主要为一些提示,具体的输入输出则将参数传递到分函数中实现。分函数有建立一元多项式、多项式升幂排序、比较项指数大小、打印多项式、加法运算、减法运算、微分运算和乘法运算等。比较须要关注的是乘法方面的实现,思路是将乘法运算分解为一系列的加法运算。不过在这里着实纠结了好多天,原本呢以为实现乘法本身应该为它再另外构造一个加法算法提供接口,以便实现它的加法迭代。但是呢,这样彻底行不通,打印出来的都是0.0,本身彻底不晓得为何,重复对着代码思考了好屡次了,以为没什么毛病,但就是行不通——算法
而后呢,大概是前天吧!本身捣弄了半天代码调试依旧不会的状况下,决定回归输出调试,因而就在乘法函数里注释掉了迭代用的加法,另外在加法循环体外面上头加了两句打印语句想看看多项式A和多项式B的每一项相乘后获得的结果是咋样的。数组
因而乎奇迹就诞生了,用x^1+2x^2+3x^3和x^1做为测试数据,莫名其妙地乘法结果就给打印出来了,彻底没有用到我费了九牛二虎之力写出来的迭代加法——数据结构
不过显示结果仍是有点小bug,显示出来的是正确结果的相反数,并且主函数返回值也不是正常的0,而是莫名其妙的3221225477函数
接着本着修bug的精神就在乘法函数里运算部分乘了个负一,这下结果就好看了,以下(返回值依旧不正常)测试
可是,天下怎么会有凭空掉馅饼这等好事!?本身再用上面给出的复杂测试数据跑了下,这下就没那么好看了,得出来的是一个明显错误的结果(。﹏。*)
并且也发现了微分算法部分的一个小bug——
好吧,只能后续继续改进了,本身应该是在指针理解上出现了问题,回头去《深刻理解C指针》。
另外,假如用户输入的两个一元多项式为相同的话,输出也会有点不正常,须要弄弄。看来有点眉目了spa
11.25这天晚上,我终于弄明白了bug的原因——丫蛋本身没把Pd给初始化!,并且打印函数若是给它的参数是个空地址的话,它会在那儿瞎转悠几圈,而后返回个不是0的返回值,直接结束程序——(还修复了打印首项有时会出现加号的小bug).net
还存在一个问题,就是若是输入的两个多项式是相同的话,减法那部分结果会不显示任何值,而不是0。得弄弄3d
(已解决)指针
OK,下面就贴下本身的代码了,折腾带注释版本,以及去掉无关注释~纯净版本^_^调试
#include<stdio.h> #include<stdlib.h> typedef struct term{ float coef; int expn; struct term *next; }term,*LinkList; typedef LinkList polynomial; int cmp(LinkList pa,LinkList pb) //比较各项指数大小 { if(pa->expn > pb->expn) return 1; else if(pa->expn == pb->expn) return 0; else return -1; } int LocateElem(LinkList L,LinkList t,LinkList *q) /*定位项数指数大小,使多项式按升幂排序 这里的*q起到内存保护的做用*/ { LinkList p1=L->next; LinkList p2=L; while(p1) { if(t->expn > p1->expn) { p1=p1->next; p2=p2->next; } else if(t->expn == p1->expn) { *q=p1; return 1; } else { *q=p2; return 0; } } *q=p2; return 0; } void CreatePolyn(polynomial P) //创建多项式所需的各项具体值 { LinkList t; LinkList q; P->coef=0.0; P->expn=-1; P->next=NULL; printf("Please input coefficient and exponent below in format like 1,2 and end with 0,0:\n"); t=(LinkList)malloc(sizeof(term)); // if(!t) exit(OVERFLOW); //借鉴教材《数据结构(C语言版)》的代码风格...没用 t->next=NULL; scanf("%f,%d",&t->coef,&t->expn); while(t->coef||t->expn) //约定0,0结束输入,实现动态输入多项式 { if(!LocateElem(P,t,&q)) /*每次输入的指数都应不一样,转移指针P->q,并且实现指数排序(这里 &q 博大精深, 利用指针的指针之妙法确保指针不被篡改,在LocateElem内部又机智地取回———)*/ { t->next=q->next; /*1.q->next = NULL,2.q->next = t, 也改变了P->next的值 P与q共享内存*/ q->next=t; //对t, 头插法, 对q, 尾插法 } t=(LinkList)malloc(sizeof(term)); // if(!t) exit(OVERFLOW); t->next=NULL; scanf("%f,%d",&t->coef,&t->expn); } } void printPolyn(polynomial P) //打印多项式 { LinkList q; q=P->next; if(!q) { printf("0\n"); //针对两多项式相同的状况 } while(q) { if(q->coef==0) /*主要针对微分的常数项状况,但是出现了下一项变为首项但其前面加号没有去掉的状况。。。*/ { printf(""); q=q->next; /*将此if结构与下面if结构分开,不耦合,解决打印首项带加号问题*/ } if(q->expn==0) //判断指数是否为零及正负,调整输出格式 { printf("%.2f",q->coef); q=q->next; } else if(q->expn>0) { printf("%.2f*x^%d",q->coef,q->expn); q=q->next; } else { printf("%.2f*x^(%d)",q->coef,q->expn); q=q->next; } if(q) //判断下一项系数正负,调整输出格式 { if(q->coef>0) printf("+"); else printf(""); } else printf("\n"); } } void AddPolyn(polynomial Pa,polynomial Pb,polynomial Pc) /*不彻底参照教科书上的思路,而是另外开辟空间存储和,不释放原来数据空间*/ { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=Pc; LinkList head=qc; LinkList s; float sum; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: s=(LinkList)malloc(sizeof(term)); //if(!s) exit(OVERFLOW); *s=*qa; qc->next=s; qc=s; qa=qa->next; break; case 0: sum=qa->coef+qb->coef; if(sum!=0.0) { s=(LinkList)malloc(sizeof(term)); //if(!s) exit(OVERFLOW); *s=*qa; s->coef=sum; qc->next=s; qc=s; qa=qa->next; qb=qb->next; } else { qc->next=qa->next; qa=qa->next; qb=qb->next; } break; case 1: s=(LinkList)malloc(sizeof(term)); // if(!s) exit(OVERFLOW); *s=*qb; qc->next=s; qc=s; qb=qb->next; break; } } qc->next=qa?qa:qb; //添加NULL尾巴 Pc=head; } void SubPolyn(polynomial Pa,polynomial Pb,polynomial Pc) /*思路同前面加法,减法变加法,前面加负号, 另外开辟空间存储差*/ { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=Pc; LinkList head=qc; LinkList s; float differ; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qb) //为减数加负号 { qb->coef=0-(qb->coef); qb=qb->next; } qb=Pb->next; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: s=(LinkList)malloc(sizeof(term)); // if(!s) exit(OVERFLOW); *s=*qa; qc->next=s; qc=s; qa=qa->next; break; case 0: differ=qa->coef+qb->coef; if(differ!=0.0) { s=(LinkList)malloc(sizeof(term)); // if(!s) exit(OVERFLOW); *s=*qa; s->coef=differ; qc->next=s; qc=s; qa=qa->next; qb=qb->next; } else { qc->next=qa->next; qa=qa->next; qb=qb->next; } break; case 1: s=(LinkList)malloc(sizeof(term)); // if(!s) exit(OVERFLOW); *s=*qb; qc->next=s; qc=s; qb=qb->next; break; } } qc->next=qa?qa:qb; Pc=head; } void AddPolyn_multi(polynomial Pa,polynomial Pb) /*构造一个能够用于乘法项数迭代的特殊加法,释放空间,和储存至Pa,方便迭代累加*/ { LinkList qa=Pa->next; //这两句致使项数错位了? LinkList qb=Pb->next; //LinkList qa=Pa; //LinkList qb=Pb; LinkList qc=Pa; LinkList head=qc; LinkList s,s1,s2; float sum; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: qc->next=qa; qc=qa; qa=qa->next; break; case 0: sum=qa->coef+qb->coef; if(sum!=0.0) { s=qb; qa->coef=sum; qc->next=qa; qc=qa; qa=qa->next; qb=qb->next; free(s); } else { s1=qa; s2=qb; qc->next=qa->next; qa=qa->next; qb=qb->next; free(s1); free(s2); } break; case 1: qc->next=qb; qc=qb; qb=qb->next; break; } } qc->next=qa?qa:qb; Pa=head; //千思万虑老子终于把你给揪出来了,原来是形参搞得鬼!? //printPolyn(Pa); //pirntf("\n"); // free(Pb); /*这句语句挺有问题,要是该指数项惟有Pb才有呢,相加后依然连接到Pb的内存空间上 */ } void MultiPolyn(polynomial Pa,polynomial Pb,polynomial Pc) /*乘法运算,分解为一系列的加法运算*/ { LinkList qa=Pa->next; LinkList qb=Pb->next; // LinkList qc=Pc; LinkList head; LinkList qd; LinkList t[20],d[20],h[20];/*,s1,s2; 这些结构体指针数组所对应的空间也应该为它们加个指数值为负一的内存! 有啊!!!*/ int i,j; //float product; /******下面添加的这两句因为思考疏忽耗费了我大半个月的精力********/ Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; /******以上*********/ while(qa&&qb) { for(j=0;j<20;j++) { d[j]=(LinkList)malloc(sizeof(term)); // if(!d[j]) exit(OVERFLOW); d[j]->coef=0.0; d[j]->expn=-1; d[j]->next=NULL; h[j]=d[j]; qd=qa; for(i=0;i<20;i++) /*二维数组应该有两个中括号吧? 不,不用,用了指针 */ { //leave it alone! t[i]=(LinkList)malloc(sizeof(term)); // if(!t[i]) exit(OVERFLOW); *t[i]=*qd; t[i]->coef=(qd->coef)*(qb->coef)*(-1); t[i]->expn=qd->expn+qb->expn; d[j]->next=t[i]; d[j]=t[i]; qd=qd->next; if(!qd) { d[j]->next=NULL; break; } } qb=qb->next; if(!qb) { h[j+1]=NULL; break; } } } //printPolyn(h[0]); //printPolyn(h[1]); //printPolyn(h[2]); //printPolyn(h[3]); /*很是奇怪,加了这两句就能够运行乘法了,不过打印出来的倒是相反数,并且返回值不是0,而是3221225477 //如今不用那个特殊加法也能够了!?难道是由于我建立的那伪二维数组实现了地址的复用??? 测试发现,若是碰到空地址,好比这个h[3],会进入一段时间死循环。。。果不其然 //本身应该是在指针的理解上出现了一些问题,得去攻读下o'reilly的《深刻理解c指针》了 */ //Not effective??? for(j=0;j<20;j++) //对了,每一列指数值不必定相同的吖! { if(!h[j+1]) //原来是你把我辛辛苦苦生成的结果的头指针给改了的#.# { head=h[j]; break; //不,不是它的错,是下面的Pc->next出现了两个-1指数项! } // printPolyn(h[j+1]); AddPolyn_multi(h[j+1],h[j]); head=h[j+1]; } // qc->next=qa?qa:qb; Pc->next=head; //擦!你丫蛋没初始化就跑进来了 //free(Pb); /*乘法部分逻辑上是没什么问题的咯,问题应该是出如今构造加法那里,哪里没有接上 */ } //(后来补充)看来不是构造加法问题 void diff(polynomial Pa, polynomial Pb) { LinkList qa=Pa->next; LinkList head; Pb->coef=0.0; Pb->expn=-1; Pb->next=NULL; head=Pb; // Pb=Pb->next; while(qa) { Pb->next=(LinkList)malloc(sizeof(term)); // if(!Pb->next) exit(OVERFLOW); Pb=Pb->next; Pb->coef=(qa->coef)*(float)(qa->expn); //coef和expn类型不一样,须要进行类型转化 Pb->expn=qa->expn-1; Pb->next=NULL; qa=qa->next; } Pb=head; } int main() { polynomial Pa; polynomial Pb; polynomial Pc; polynomial Pd; Pa=(LinkList)malloc(sizeof(term)); Pb=(LinkList)malloc(sizeof(term)); Pc=(LinkList)malloc(sizeof(term)); // Pc->next=NULL; Pd=(LinkList)malloc(sizeof(term)); // Pd->next=NULL; CreatePolyn(Pa); printf("Pa="); printPolyn(Pa); CreatePolyn(Pb); printf("Pb="); printPolyn(Pb); /* Pc = Pa; Pd = Pb; */ printf("\nPa'="); diff(Pa,Pc); printPolyn(Pc); printf("Pa+Pb="); AddPolyn(Pa,Pb,Pc); printPolyn(Pc); printf("Pa-Pb="); SubPolyn(Pa,Pb,Pc); printPolyn(Pc); printf("Pa*Pb="); MultiPolyn(Pa,Pb,Pd); printPolyn(Pd); // printf("\n"); /* printf("Pb'="); diff(Pb,Pc); printPolyn(Pc); */ return 0;
#include<stdio.h> #include<stdlib.h> typedef struct term{ float coef; int expn; struct term *next; }term,*LinkList; typedef LinkList polynomial; int cmp(LinkList pa,LinkList pb) { if(pa->expn > pb->expn) return 1; else if(pa->expn == pb->expn) return 0; else return -1; } int LocateElem(LinkList L,LinkList t,LinkList *q) { LinkList p1=L->next; LinkList p2=L; while(p1) { if(t->expn > p1->expn) { p1=p1->next; p2=p2->next; } else if(t->expn == p1->expn) { *q=p1; return 1; } else { *q=p2; return 0; } } *q=p2; return 0; } void CreatePolyn(polynomial P) { LinkList t; LinkList q; P->coef=0.0; P->expn=-1; P->next=NULL; printf("Please input coefficient and exponent in format like 1,2 and end with 0,0 :\n"); t=(LinkList)malloc(sizeof(term)); t->next=NULL; scanf("%f,%d",&t->coef,&t->expn); while(t->coef||t->expn) { if(!LocateElem(P,t,&q)) { t->next=q->next; q->next=t; } t=(LinkList)malloc(sizeof(term)); t->next=NULL; scanf("%f,%d",&t->coef,&t->expn); } } void printPolyn(polynomial P) { LinkList q; q=P->next; if(!q) { printf("0\n"); } while(q) { if(q->coef==0) { printf(""); q=q->next; } if(q->expn==0) { printf("%.2f",q->coef); q=q->next; } else if(q->expn>0) { printf("%.2f*x^%d",q->coef,q->expn); q=q->next; } else { printf("%.2f*x^(%d)",q->coef,q->expn); q=q->next; } if(q) { if(q->coef>0) printf("+"); else printf(""); } else printf("\n"); } } void AddPolyn(polynomial Pa,polynomial Pb,polynomial Pc) { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=Pc; LinkList head=qc; LinkList s; float sum; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: s=(LinkList)malloc(sizeof(term)); *s=*qa; qc->next=s; qc=s; qa=qa->next; break; case 0: sum=qa->coef+qb->coef; if(sum!=0.0) { s=(LinkList)malloc(sizeof(term)); *s=*qa; s->coef=sum; qc->next=s; qc=s; qa=qa->next; qb=qb->next; } else { qc->next=qa->next; qa=qa->next; qb=qb->next; } break; case 1: s=(LinkList)malloc(sizeof(term)); *s=*qb; qc->next=s; qc=s; qb=qb->next; break; } } qc->next=qa?qa:qb; Pc=head; } void SubPolyn(polynomial Pa,polynomial Pb,polynomial Pc) { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=Pc; LinkList head=qc; LinkList s; float differ; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qb) { qb->coef=0-(qb->coef); qb=qb->next; } qb=Pb->next; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: s=(LinkList)malloc(sizeof(term)); *s=*qa; qc->next=s; qc=s; qa=qa->next; break; case 0: differ=qa->coef+qb->coef; if(differ!=0.0) { s=(LinkList)malloc(sizeof(term)); *s=*qa; s->coef=differ; qc->next=s; qc=s; qa=qa->next; qb=qb->next; } else { qc->next=qa->next; qa=qa->next; qb=qb->next; } break; case 1: s=(LinkList)malloc(sizeof(term)); *s=*qb; qc->next=s; qc=s; qb=qb->next; break; } } qc->next=qa?qa:qb; Pc=head; } void diff(polynomial Pa,polynomial Pb) { LinkList qa=Pa->next; LinkList head; Pb->coef=0.0; Pb->expn=-1; Pb->next=NULL; head=Pb; while(qa) { Pb->next=(LinkList)malloc(sizeof(term)); Pb=Pb->next; Pb->coef=(qa->coef)*(float)(qa->expn); Pb->expn=qa->expn-1; Pb->next=NULL; qa=qa->next; } Pb=head; } void AddPolyn_multi(polynomial Pa,polynomial Pb) { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=qa; LinkList head=qc; LinkList s,s1,s2; float sum; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: qc->next=qa; qc=qa; qa=qa->next; break; case 0: sum=qa->coef+qb->coef; if(sum!=0.0) { s=qb; qa->coef=sum; qc->next=qa; qc=qa; qa=qa->next; qb=qb->next; free(s); } else { s1=qa; s2=qb; qc->next=qa->next; qa=qa->next; qb=qb->next; free(s1); free(s2); } break; case 1: qc->next=qb; qc=qb; qb=qb->next; break; } } qc->next=qa?qa:qb; Pa=head; } void MultiPolyn(polynomial Pa,polynomial Pb,polynomial Pc) { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList head; LinkList qd; LinkList t[20],d[20],h[20]; int i,j; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qa&&qb) { for(j=0;j<20;j++) { d[j]=(LinkList)malloc(sizeof(term)); d[j]->coef=0.0; d[j]->expn=-1; d[j]->next=NULL; h[j]=d[j]; qd=qa; for(i=0;i<20;i++) { t[i]=(LinkList)malloc(sizeof(term)); *t[i]=*qd; t[i]->coef=(qd->coef)*(qb->coef)*(-1); t[i]->expn=qd->expn+qb->expn; d[j]->next=t[i]; d[j]=t[i]; qd=qd->next; if(!qd) { d[j]->next=NULL; break; } } qb=qb->next; if(!qb) { h[j+1]=NULL; break; } } } for(j=0;j<20;j++) { if(!h[j+1]) { head=h[j]; break; } AddPolyn_multi(h[j+1],h[j]); head=h[j+1]; } Pc->next=head; } int main() { polynomial Pa; polynomial Pb; polynomial Pc; polynomial Pd; Pa=(LinkList)malloc(sizeof(term)); Pb=(LinkList)malloc(sizeof(term)); Pc=(LinkList)malloc(sizeof(term)); Pd=(LinkList)malloc(sizeof(term)); CreatePolyn(Pa); printf("Pa="); printPolyn(Pa); CreatePolyn(Pb); printf("Pb="); printPolyn(Pb); printf("\nPa'="); diff(Pa,Pc); printPolyn(Pc); printf("Pa+Pb="); AddPolyn(Pa,Pb,Pc); printPolyn(Pc); printf("Pa-Pb="); SubPolyn(Pa,Pb,Pc); printPolyn(Pc); printf("Pa*Pb="); MultiPolyn(Pa,Pb,Pd); printPolyn(Pd); return 0; }
利用单链表实现一元多项式的表示及相加