一元稀疏多项式简单计数器
![一元稀疏多项式简单计数器](https://img.360docs.net/img5c/1auko64p698dyq88mbjwvy2gvnocxqat-c1.webp)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一元稀疏多项式简单计数器
题目:编制一个演示一元稀疏多项式简单计数器的程序
完成日期:2015.4.9
一、需求分析
1.1本演示程序中,多项式是以带头结点的单链表存储的,在单链表中有两个数据域,分别存储多项式的一个节点的系数,指数;还有一个指针域,存储指向下一个节点的指针。
1.2演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令;相应的输入数据和运算结果显示在其后。
1.3程序执行的命令包括:
1)构造多项式a;2)构造多项式b;3)输出多项式,并且多项式的序列按指数的降序排列;4)求a+b;5)求a-b;6)求a*b;7) 求多项式a的导函数a’;8)求多项式在x处的值。
1.4测试数据
(1)(2x+5x^8-3.1x^11)+(7-5x^8+11x^9)
=(-3.1x^11+11x^9+2x+7)
(2)(6x^(-3)-x+4.4x^2-1.2x^9)-(-6x^(-3)+5.4x^2-x^2-x ^2+7.8x^15)=(-7.8x^15-1.2x^9+12x^(-3)-x)
(3)(1+x+x^2+x^3+x^4+x^5)+(-x^3-x^4)=(1+x+x^2+x ^5)
(4)(x+x^3)+(-x-x^3)=0
(5)(x+x^100)+(x^100+x^200)=(x+2x^100+x^200)
(6)(x+x^2+x^3)+0=x+x^2+x^3
(7)互换上述测试数据中的前后两个多项式
二、概要设计
为实现上述程序的功能,应以带头结点的单链表表示多项式。为此,需要一个抽象数据类型:单链表。
2.1单链表的抽象数据类型定义
ADT LinkList{
数据对象:D={ai|ai∈TermSet,i=1,2,…,m,m≥0
TermSet中的每个元素包含一个表示系数的实数和表示指数的整数}
数据关系:R1={ 基本操作: CreatLinkList(&p,m) 操作结果:输入m项的系数和指数,建立一元多项式p。 DestoryLinkList(&p) 初始条件:一元多项式p已存在。 操作结果:销毁一元多项式p. PrintLinkList(p) 初始条件:一元多项式p已存在。 操作结果:打印输出一元多项式p. AddLinkList(&pa,&pb) 初始条件:一元多项式pa和pb已存在。 操作结果:完成多项式的相加运算,即:pa=pa+pb,并销毁一元多项式pb. SubtractLinkList(&pa,&pb) 初始条件:一元多项式pa和pb已存在。 操作结果:完成多项式的想减运算,即:pa=pa-pb,并销毁一元多项式pb. MultiLinkList(&pa,&pb) 初始条件:一元多项式pa和pb已存在。 操作结果:完成多项式相乘运算,即:pa=pa*pb,并销毁一元多项式pb. }ADT LinkList 2.2本程序包括个模块: 1)主程序模块: Void main(){ 初始化; 输出菜单; While(1){ 接受命令; 处理命令; }(循环一直为真直至接受退出命令); 2)单链表单元模块——实现单链表的抽象数据类型; 3)结点结构单元模块——定义单链表的结点结构。 各模块之间的调用关系如下: 主程序模块 单链表单元模块 结点结构单元模块 三、详细设计 3.1元素类型、结点类型和指针类型 typedef int Status; typedef int ElemType; typedef struct LNode{ float coef; //定义项的系数 ElemType expn; //定义项的指数 struct LNode *next; //指向下一个节点 }LNode,*LinkList; Status MakeNode(LinkList &p,LinkList head) { //分配由p指向下一个多项式的头结点head、后继为空的结点,并返回TRUE, //若分配失败,则返回FALSE p= (LinkList)malloc(sizeof(struct LNode)); if(!p)return false; p=head;p->next=null;return ture; void FreeNode(LinkList &p) { //释放p所指结点 free(q1); q1=q2; q2=q2->next; } 3.2单链表的基本操作设置如下: void Insert(LinkList p,LinkList h); //将节点p插入到多项式链表h LinkList CreateLinkList(LinkList head,int m); //建立一个头指针为head、项数为m的一元多项式,并返回该多项式的头结点; //若分配空间失败,则返回FALSE void DestroyLinkList(LinkList p); //销毁多项式p void PrintLinkList(LinkList P); //输出构造的一元多项式P Status compare(LinkList a,LinkList b) //节点进行比较: a的指数>b的指数return 1; a的指数==b的指数return 0; a的指数 LinkList AddLinkList(LinkList pa,LinkList pb) //求解并建立多项式a+b,返回其头指针 LinkList SubtractLinkList(LinkList pa,LinkList pb) //求解并建立多项式a-b,返回其头指针 float ValueLinkList(LinkList head,int x) //输入x值,计算并返回多项式的值 LinkList Derivative(LinkList head) //求解并建立导函数多项式,并返回其头指针 LinkList MultiplyLinkList(LinkList pa,LinkList pb) //求解并建立多项式a*b,返回其头指针 其中部分操作的伪码如下: LinkList CreateLinkList(LinkList head,int m) { p=head=(LinkList)malloc(sizeof(struct LNode)); head->next=NULL; for(i=0;i { p=(LinkList)malloc(sizeof(struct LNode)); //建立新结点以接收数据 printf("请输入第%d项的系数与指数:",i+1); scanf("%f %d",&p->coef,&p->expn); Insert(p,head); //调用Insert函数插入结点 } return head; }// CreateLinkList Status compare(LinkList a,LinkList b){ if(a&&b){ if(!b||a->expn>b->expn) return 1; else if(!a||a->expn else return 0;} else if(!a&&b) return -1;//a多项式已空,但b多项式非空 else return 1;//b多项式已空,但a多项式非空 }// compare float ValueLinkList(LinkList head,int x){ //输入x值,计算并返回多项式的值 for(p=head->next;p;p=p->next){ t=1; for(i=p->expn;i!=0;) // i 为指数的系数pow(x,i) { if(i<0){t/=x;i++;} //指数小于0,进行除法 else{t*=x;i--;} } //指数大于0,进行乘 法sum+=p->coef*t; } return sum;}// ValueLinkList LinkList MultiplyLinkList(LinkList pa,LinkList pb){//求解并建立多项式a*b,返回其头指针 LinkList qa=pa->next; LinkList qb=pb->next; hf=(LinkList)malloc(sizeof(struct LNode));//建立头结点 hf->next=NULL; for(;qa;qa=qa->next) { for(qb=pb->next;qb;qb=q b->next) {pf=(LinkList)malloc(sizeof(struct LNode)); pf->coef=qa->coef*qb->coef; pf->expn=qa->expn+qb->expn; Insert(pf,hf); }//调用Insert函数以合并指数相同的项 }return hf;}// MultiplyLinkList 3.3主函数和其他函数的伪码算法 void main(){//主函数 Initiation(); //多项式初始化 PrintCommand();//输出菜单 while(1){ //循环一直为真知道选择j||J即退出命令时,程序退出 printf("\n请选择操作:"); scanf("%c",&flag); Interpter(flag); //具体的操作命令 }} //main void Initiation() { printf("请输入a的项数:"); scanf("%d",&m); pa=CreateLinkList(pa,m);//建立多项式a printf("请输入b的项数:"); scanf("%d",&n); pb=CreateLinkList(pb,n);//建立多项式b printf("-------------------多项式已创建-----------------------\n"); }// Initiation void PrintCommand(){ //输出菜单 显示键入命令的提示信息; Printf (’A’,’B’,’C’,’D’,’E’,’F’,’G’,’H’,’I ’,’J’); }// PrintCommand void Interpter(char flag) { //具体的操作命令 switch(flag) { case 'A': case 'a':{ PrintLinkList(pa); break;} case 'B':case 'b':{ PrintLinkList(pb); break;} case'C': case'c': { pc=Derivative(pa); PrintLinkList(pc);break;} case'D': case'd': {Derivative(pb); PrintLinkList(pc); break;} case'E': case'e': { ValueLinkList(pa,x));break;} case'F': case'f':{ ValueLinkList(pb,x));break;} case'G': case'g': { AddLinkList(pa,pb); PrintLinkList(pc); break; } case'H': case'h': { SubtractLinkList(pa,pb));PrintLinkList(pc); break;} case'I':case'i':{pc=MultiplyLinkList(pa,pb);); PrintLinkList(pc);break;} case'J':case'j': { DestroyLinkList(pa); DestroyLinkList(pb);exit(0) ; } default:printf("\n 您的选择错误,请重新选择!\n");} } // Interpter 3.4函数的调用关系图反映了演示程序的层次结构: Main Initiation PrintCommand Interpter CreateLinkList PrintLK Derivative ValueLK AddLK SubtractLK MultiplyLK DestroyLK PrintLK PrintLK PrintLK PrintLK exit(0) 说明LK :LinkList 即多项式节点 函数说明: Initiation(); //多项式初始化PrintCommand(); //输出菜单 Interpter() ; //具体的操作命令PrintLinkList() ; //打印多项式(降序输出) Derivative(); //多项式求导 ValueLinkList(); //多项式求值 AddLinkList() ; //两个多项式相加 SubtractLinkList(); //两个多项式相减MultiplyLinkList(); //两个多项式相乘DestroyLinkList(); //销毁多项式 compare() ; //两个节点比较CreateLinkList(); //创建多项式 Insert() ; //将节点插入已知多项式中 四、调试分析 4.1刚开始的时候由于对多项式的减法考虑不周全,代码很复杂,后来经过仔细思考,减法时把每项的系数变成它的相反数,然后调用加法的函数即可,但是实现了减法之后要把系数恢复,不然会影响后面的运算。 4.2求多项式在x处的值的函数在刚开始的时候出现过警告,虽然警告不会影响程序的运行,但是运算的结果不精确。之前函数的类型是int,但是里面的多项式的系数是浮点型的,而sum又是整型的,但是这样得不到小数点后面的数值,导致结果不精确。后来经改进,把函数的类型及sum的类型均改为float型。 五、用户使用手册 5.1此程序的整体架构: 主函数里有三个函数,Initialization(初始化)、PrintCommand(打印命令)、Interpret(解释并执行命令)。在Interpret函数中调用了其他的函数,以达到执行命令的目的。 5.2在输入命令时要注意在输入多项式的每一项的系数和指数必须有空格,否则可能会解释命令出错。在完成每一条的命令输入时要键入Enter. 六、测试结果 (程序输入的相关命令) 七、附录(源代码): #include #include #include #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; typedef int ElemType; typedef struct LNode{ float coef; //定义项的系数 ElemType expn; //定义项的指数 struct LNode *next; //指向下一个节点 }LNode,*LinkList; /*全局节点初始化多项式节点为空*/ static LinkList pa=NULL; static LinkList pb=NULL; static LinkList pc=NULL; /*将节点p插入到多项式链表h*/ void Insert(LinkList p,LinkList h){ if(p->coef==0) free(p); //系数为0的话释放结点 else{ LinkList q1,q2; q1=h; q2=h->next; while(q2&&p->expn q1=q2; q2=q2->next; } if(q2&&p->expn==q2->expn){//将指数相同相合并 q2->coef+=p->coef; free(p); if(!q2->coef){//系数为0的话释放结点 q1->next=q2->next; free(q2); } } else{ //指数为新时将结点插入 p->next=q2; q1->next=p; } } } //创建一元多项式 LinkList CreateLinkList(LinkList head,int m){ //建立 一个头指针为head、项数为m的一元多项式 int i; LinkList p; p=head=(LinkList)malloc(sizeof(struct LNode)); head->next=NULL; for(i=0;i { p=(LinkList)malloc(sizeof(struct LNode)); //建立新结点以接收数据 printf("请输入第%d项的系数与指数:",i+1); scanf("%f %d",&p->coef,&p->expn); Insert(p,head); //调用Insert函数插入结点 } return head; } void DestroyLinkList(LinkList p){ //销毁多项式p LinkList q1,q2; q1=p->next; q2=q1->next; while(q1->next) {free(q1); q1=q2; q2=q2->next; } } //输出构造的一元多项式P void PrintLinkList(LinkList P){ LinkList q=P->next; int flag=1;//项数计数器 if(!q) { //若多项式为空,输出0 putchar('0'); printf("\n"); return; } while(q) { if(q->coef>0&&flag!=1) putchar('+'); //系数大于0且不是第一项 if(q->coef!=1&&q->coef!=-1) {//系数非1或-1的普通情况 printf("%g",q->coef); if(q->expn==1) putchar('X'); else if(q->expn) printf("X^%d",q->expn); } else { if(q->coef==1) { if(!q->expn) putchar('1'); else if(q->expn==1) putchar('X'); else printf("X^%d",q->expn); } if(q->coef==-1) { if(!q->expn) printf("-1"); else if(q->expn==1) printf("-X"); else printf("-X^%d",q->expn); } } q=q->next; flag++; } printf("\n"); } // 节点进行比较 // a的指数>b的指数return 1 // a的指数==b的指数return 0 // a的指数 Status compare(LinkList a,LinkList b){ if(a&&b) { if(!b||a->expn>b->expn) return 1; else if(!a||a->expn else return 0; } else if(!a&&b) return -1;//a多项式已空,但b多项式非空 else return 1;//b多项式已空,但a多项式非空 } LinkList AddLinkList(LinkList pa,LinkList pb){//求解并建立多项式a+b,返回其头指针 LinkList qa=pa->next; LinkList qb=pb->next; LinkList headc,hc,qc; hc=(LinkList)malloc(sizeof(struct LNode));//建立头结点 hc->next=NULL; headc=hc; while(qa||qb){ qc=(LinkList)malloc(sizeof(struct LNode)); switch(compare(qa,qb)){ case 1: { qc->coef=qa->coef; qc->expn=qa->expn; qa=qa->next; break; } case 0: { qc->coef=qa->coef+qb->coef;