第一个多项式有n项,第二个多项式有m项。以下均为最坏的情况。
操作 |
时间复杂度(T(n)) |
空间复杂度(S(n)) |
判断是否为空 |
O(1) |
O(1) |
得到长度 |
O(n) |
O(1) |
求和 |
O(n+m) |
O(1) |
求差 |
O(n+m) |
O(1) |
求积 |
O(n*m) 双重循环 |
O(n*m) 最坏的情况就是相乘后每一项的指数都不一样,这样就有n*m项(这种情况概率很低) |
/* 数据结构分析与学习专栏 * Copyright (c) 2015, 山东大学计算机科学与技术专业学生 * All rights reserved. * 作 者: 高祥 * 完成日期: 2015 年 3 月 28 日 * 版 本 号:006 *任务描述:单链表的应用,模拟一元多项式的运算。 * 1:建立一元多项式 ; * 2:打印一元多项式 ; * 3:输出一元多项式的项数 ; * 4:判断一元多项式是否为空 ; * 5:一元多项式求和 ; * 6:一元多项式求差; * 7:一元多项式求积 ; * 8:销毁一元多项式; *主要函数: * 1.InitPoly(Polynome &P);//初始化头结点 * 2.FindPoly(Polynome P,Polynome&before,Polynome &after,int expo); //建立一元多项式的辅助函数 //参数说明: //P是已经存在的一元多项式的头结点指针;before是满足指数小于将要插入结点指数的第一个结点指针 //after是满足指数大于等于将要插入结点指数的第一个结点指针;expo是将要插入的结点指数 //注意:before与after指针必须引用传值,达到修改CreatPoly()函数中指针的目的,且after=before->next * 3.CreatPoly(Polynome P,int polysize);//建立一元多项式 * 4.Output(Polynome P);//输出一元多项式 * 5.int PolyLength(Polynome P);//求一元多项式的项数 * 6.Status IsEmptyPoly(Polynome P);//判断一元多项式是否为空 * 7.AddPoly(Polynome P1,Polynome&P2);//一元多项式相加,将结果赋给多项式P1 * 8.SubtractPoly(Polynome P1,Polynome&P2);//一元多项式相减,将结果赋给P1 * 9.MultiplyPoly(Polynome &P1,Polynome&P2);//一元多项式相乘,将结果赋给P1 * 10.DestroyPoly(Polynome &P);//销毁多项式 *主要优点: 1. 创建多项式:用户输入任意组由用户决定的数据(无序状态),创建的多项式是合并同类项后并且结点的指数大小依次递增(通过辅助函数FindPoly来实现该排序的功能),不多含任何一项,在合并的过程中,某些项合并后消失,那么程序接着会释放无用节点的内存达到内存最少、项数最精简的效果。 例如输入9组数据:-5 0 5 0 0 1 1 2 1 2 -2 2 -7 1 7 3 21 4 输出为:P(x)=(-7)x+(7)x^(3)+(21)x^(4) 2. 输出多项式:符合人们书写的习惯。做到了:非第一项的系数为正前面加‘+’;系数为1省略输出;常数为1不能省略输出;指数为0不输出x;指数为1不输出指数;每输出10项换行。每个数字用括号括起来是因为:当系数很大时,系统会输出如‘1.009e+098’之类的数字,为了便于识别‘+’、‘-’符号,因此每个数字均加了括号。 3. 求多项式的和差:做到了:内存最优,运算后消失的项和指数相同冗余的项均释放了内存;运算后结果依然是按照指数的升序排序。 4. 求多项式的积:同样做到了内存最优。但是没想到怎样优化时间空间复杂度,采取最笨的一项乘一项的方式,两项相乘完以后,指数、系数均可能改变,为了依然按照指数升序排列,再次使用辅助函数FindPoly来实现该排序的功能,就好像是手动输入运算后的系数和指数一样,达到排序的效果。运算结束,销毁原来的两条多项式,将结果移交给第一个头结点。 *注意:以上函数中的形参的&均是必要的,都不能去掉 */ #include<iostream> #include<cstdlib> using namespace std; #define OK 1 #define FALSE 0 #define ERROR 0 const int INF=2000000000; typedef int Status; typedef struct { double coef; int expo; } ElemType; typedef struct LNode { ElemType data; struct LNode *next; } LNode,*LinkList; typedef LinkList Polynome; void InitPoly(Polynome &P);//初始化头结点 void FindPoly(Polynome P,Polynome&before,Polynome &after,int expo);//建立一元多项式的辅助函数 //参数说明: //P是已经存在的一元多项式的头结点指针;before是满足指数小于将要插入结点指数的第一个结点指针 //after是满足指数大于等于将要插入结点指数的第一个结点指针;expo是将要插入的结点指数 //注意:before与after指针必须引用传值,达到修改CreatPoly()函数中指针的目的,且after=before->next void CreatPoly(Polynome P,int polysize);//建立一元多项式 void Output(Polynome P);//输出一元多项式 int PolyLength(Polynome P);//求一元多项式的项数 Status IsEmptyPoly(Polynome P);//判断一元多项式是否为空 void AddPoly(Polynome P1,Polynome&P2);//一元多项式相加,将结果赋给多项式P1 void SubtractPoly(Polynome P1,Polynome&P2);//一元多项式相减,将结果赋给P1 void MultiplyPoly(Polynome &P1,Polynome&P2);//一元多项式相乘,将结果赋给P1 void DestroyPoly(Polynome &P);//销毁多项式 void Interaction(); int main() { Polynome P1=NULL,P2=NULL;//初始化为空指针最安全 Interaction(); int operate; while(cin>>operate) { switch(operate) { case 0: goto END; case 1: InitPoly(P1); cout<<"请输入要创建的一元多项式的项数:"; int polysize; cin>>polysize; CreatPoly(P1,polysize); break; case 2: Output(P1); break; case 3: cout<<"该一元多项式的项数为:"<<PolyLength(P1)<<endl; break; case 4: if(!IsEmptyPoly(P1)) { cout<<"该一元多项式不为空。\n"; } else { cout<<"该一元多项式为空。\n"; } break; case 5: InitPoly(P2); cout<<"请输入要创建的一元多项式的项数:"; cin>>polysize; CreatPoly(P2,polysize); AddPoly(P1,P2); break; case 6: InitPoly(P2); cout<<"请输入要创建的一元多项式的项数:"; cin>>polysize; CreatPoly(P2,polysize); SubtractPoly(P1,P2); break; case 7: InitPoly(P2); cout<<"请输入要创建的一元多项式的项数:"; cin>>polysize; CreatPoly(P2,polysize); MultiplyPoly(P1,P2); break; case 8: DestroyPoly(P1); cout<<"销毁一元多项式成功。进行其他操作请先创建一元多项式。\n"; break; default: cout<<"请输入正确的操作数!\n"; break; } } END: DestroyPoly(P1); DestroyPoly(P2); return 0; } void InitPoly(Polynome &P)//初始化头结点 { P=(Polynome)malloc(sizeof(LNode)); P->next=NULL; P->data.coef=0.0;//头结点的系数为0,后续所有结点的系数均不为0, P->data.expo=-INF;//头结点的指数为负无穷,便于实现按照指数升序排列 cout<<"头结点初始化成功。\n"; } void FindPoly(Polynome P,Polynome&before,Polynome &after,int expo)//建立一元多项式的辅助函数 //参数说明: //P是已经存在的一元多项式的头结点指针;before是满足指数小于将要插入结点指数的第一个结点指针 //after是满足指数大于等于将要插入结点指数的第一个结点指针;expo是将要插入的结点指数 //注意:before与after指针必须引用传值,达到修改CreatPoly()函数中指针的目的,且after=before->next { //分类讨论: if(!IsEmptyPoly(P))//一元多项式已经存在项 { before=P; after=P->next; while(1) { if(before->data.expo<expo&&(after==NULL||(after&&after->data.expo>=expo))) //after指针为空(说明要插在当前一元多项式的最后面)或者不为空且满足大小条件 { return; } if(after)//after指针不为空,向后更新指针 { before=after; after=after->next; } } } //一元多项式为空: before=P; after=NULL; } void CreatPoly(Polynome P,int polysize) { cout<<"请输入"<<polysize<<"组数据,每组数据第一个数字是系数(任意非零实数),第二个数字是指数(任意整数),数字之间用空格间隔:\n"; for(int i=1; i<=polysize; i++) { double coef; int expo; cin>>coef>>expo; if(coef)//系数为0的项不用建立 { Polynome before,after; FindPoly(P,before,after,expo);//找到合适位置 if(after&&after->data.expo==expo) //若将要插入的项的指数已经存在,那么无需开辟新内存,只需要修改存在项的系数 { after->data.coef=after->data.coef+coef; if(after->data.coef==0)//修改后若系数为0,即该项消失,那么释放存在项的内存 { before->next=after->next;//删除该结点,改变指针链接 free(after); } } else//若将要插入的项的指数不存在,那么需开辟新内存,创建新结点 { Polynomeq=(Polynome)malloc(sizeof(LNode)); q->data.coef=coef; q->data.expo=expo; before->next=q;//更新指针 q->next=after; } } } cout<<"您创建的多项式为(合并同类项后):\n"; Output(P); } void Output(Polynome P)//输出一元多项式 { if(!IsEmptyPoly(P)) { cout<<"P(x)="; Polynome q=P->next; int kase=0;//控制一行输出的项数和开头‘+’号的输出 while(q) { if(kase!=0)//不为第一项,前面填上‘+’号 { cout<<"+"; } if(q->data.coef>0)//系数大于0 { if(q->data.coef!=1||(q->data.coef==1&&q->data.expo==0))//不为1的正系数或者为1的常数才输出系数 { cout<<"("<<q->data.coef<<")"; } } else//系数小于0直接输出系数 { cout<<"("<<q->data.coef<<")"; } if(q->data.expo)//指数不为0才输出x { cout<<"x"; if(q->data.expo!=1)//指数为1不输出 { cout<<"^("<<q->data.expo<<")"; } } kase++;//输出项+1 q=q->next;//更新指针 if(kase%10==0)//每行输出10项 { cout<<endl; } } cout<<endl; return; } cout<<"多项式为空,无法输出。请先创建多项式。\n"; } int PolyLength(Polynome P)//求一元多项式的项数 { int num=0; if(!IsEmptyPoly(P)) { P=P->next; while(P) { num++; P=P->next; } } return num; } Status IsEmptyPoly(Polynome P)//判断一元多项式是否为空 { if(P&&P->next) { return FALSE; } return OK; } void AddPoly(Polynome P1,Polynome&P2)//一元多项式相加,将结果赋给多项式P1 { if(!IsEmptyPoly(P1)&&!IsEmptyPoly(P2))//两个多项式均不为空 { Polynome p1,p2,q,r; p1=P1->next,p2=P2->next;//两个用来遍历的指针 q=P1;//相加后的多项式的头结点 while(p1&&p2) { if(p1->data.expo<p2->data.expo)//连接到P1链本身的节点 { r=p1->next; //预存将要访问的节点指针,因为q是P1上的指针,省去该语句后, //语句:q->next=p1;q=p1可能会修改p1原来的指向,导致错误 q->next=p1; q=p1;//更新指针 p1=r; } else if(p1->data.expo==p2->data.expo)//系数相加后连接到P1链本身的节点 { r=p1->next; p1->data.coef=p1->data.coef+p2->data.coef; if(p1->data.coef==0)//合并项后消失,释放内存 { free(p1); } else { q->next=p1; q=p1; } p1=r;//更新指针 r=p2->next; free(p2);//该结点相加后的多项式中用不到,所以释放其内存 p2=r; } else//连接到P2链的节点 { r=p2->next; q->next=p2; q=p2;//更新指针 p2=r; } } q->next= p1==NULL?p2:p1;//链接到有剩余项的链的剩余的第一个指针即可完成运算 cout<<"相加后的一元多项式为:\n"; Output(P1); //DestroyPoly(P2);语句不能加,因为P2链的许多结点链接到了新链中,只需要释放P2链中与P1链指数相同的节点和P2的头结点 free(P2); P2=NULL; return; } cout<<"一元多项式为空,无法操作。\n"; } void SubtractPoly(Polynome P1,Polynome&P2)//一元多项式相减,将结果赋给P1 { if(!IsEmptyPoly(P1)&&!IsEmptyPoly(P2))//两个多项式均不为空 { Polynome p1,p2,q,r; p1=P1->next,p2=P2->next;//两个用来遍历的指针 q=P1;//相加后的多项式的头结点 while(p1&&p2) { if(p1->data.expo<p2->data.expo)//连接到P1链本身的节点 { r=p1->next; //预存将要访问的节点指针,因为q是P1上的指针,省去该语句后, //语句:q->next=p1;q=p1可能会修改p1原来的指向,导致错误 q->next=p1; q=p1;//更新指针 p1=r; } else if(p1->data.expo==p2->data.expo)//系数相加后连接到P1链本身的节点 { r=p1->next; p1->data.coef=p1->data.coef-p2->data.coef; if(p1->data.coef==0)//合并项后消失,释放内存 { free(p1); } else { q->next=p1; q=p1; } p1=r;//更新指针 r=p2->next; free(p2);//该结点相加后的多项式中用不到,所以释放其内存 p2=r; } else//连接到P2链的节点 { p2->data.coef=-p2->data.coef;//第二个多项式的项的系数变号(被减的) r=p2->next; q->next=p2; q=p2;//更新指针 p2=r; } } q->next= p1==NULL?p2:p1;//链接到有剩余项的链的剩余的第一个指针即可完成运算 cout<<"相减后的一元多项式为:\n"; Output(P1); //DestroyPoly(P2);语句不能加,因为P2链的许多结点链接到了新链中,只需要释放P2链中与P1链指数相同的节点和P2的头结点 free(P2); P2=NULL; return; } cout<<"一元多项式为空,无法操作。\n"; } void MultiplyPoly(Polynome &P1,Polynome&P2)//一元多项式相乘,将结果赋给P1 { if(!IsEmptyPoly(P1)&&!IsEmptyPoly(P2)) { Polynome p1=P1->next,p2=P2->next; Polynome P;//开辟一条新链,最后将P1的头结点指向新链 InitPoly(P);//初始化新链的头结点 //双重循环:依次用第一个多项式的每一项乘以第二个多项式的每一项,将结果项的系数和指数存起来 //视为“输入的”,采取创建一元多项式的思路,将每一组数据插入到新链中 while(p1) { p2=P2->next; while(p2) { doublecoef=(p1->data.coef)*(p2->data.coef);//结果项的系数 intexpo=p1->data.expo+p2->data.expo;//结果项的指数 //以下同CreatPoly函数 if(coef)//系数为0的项不用建立 { Polynome before,after; FindPoly(P,before,after,expo);//找到合适位置 if(after&&after->data.expo==expo) //若将要插入的项的指数已经存在,那么无需开辟新内存,只需要修改存在项的系数 { after->data.coef=after->data.coef+coef; if(after->data.coef==0)//修改后若系数为0,即该项消失,那么释放存在项的内存 { before->next=after->next;//删除该结点,改变指针链接 free(after); } } else//若将要插入的项的指数不存在,那么需开辟新内存,创建新结点 { Polynomeq=(Polynome)malloc(sizeof(LNode)); q->data.coef=coef; q->data.expo=expo; before->next=q;//更新指针 q->next=after; } } p2=p2->next;//后移指针 } p1=p1->next;//后移指针 } DestroyPoly(P1);//销毁两个原来的多项式 DestroyPoly(P2); P1=P;//将结果赋给P1链 cout<<"相乘后的一元多项式为:\n"; Output(P1); return; } cout<<"一元多项式为空,无法操作。\n"; } void DestroyPoly(Polynome &P)//销毁多项式 { while(P) { Polynome q=P->next; free(P); P=q; } P=NULL; } void Interaction() { cout<<"请输入对应操作的序号:\n"; cout<<"0:退出程序;\n"; cout<<"1:建立一元多项式;\n"; cout<<"2:打印一元多项式;\n"; cout<<"3:输出一元多项式的项数;\n"; cout<<"4:判断一元多项式是否为空;\n"; cout<<"5:一元多项式求和;\n"; cout<<"6:一元多项式求差;\n"; cout<<"7:一元多项式求积;\n"; cout<<"8:销毁一元多项式;\n"; }