一元多项式运算器的分析与实现
-
首先,需要解决一元多项式在计算机中的存储问题。对于一元多项式: P = p0 + p1x + …+pnx^n ;在计算机中,可以用一个线性表来表示: P = (p0,p1,…,pn), 但是对于形如 S(x) = 1 + 5x^10 000 -12x^15 000 的多项式,上面的方法显然不合适,会有很多的项系数为0,造成存储空间的浪费,因此只需要存储非0系数项。
-
为了实现任意多项式的运算,考虑到运算时有较多的插入、删除操作,选择单链表作为存储结构比较方便,每个结点有三个域:系数、指数和指针。其数据结构如下所示:**
typedef struct DuoXiangShi{ int xi_shu; //系数 int zhi_shu; //指数 struct DuoXiangShi *next; //指向下一个结点的指针 }Polyn, *LinkPolyn;
一、建立多项式
-
通过键盘输入一组多项式的系数和指数,用尾插法建立一元多项式的链表。以输入系数0为结束标志,并约定建立一元多项式链表时,总是按指数从小到大的顺序排列。
/*用尾插法创建链表*/ LinkPolyn CreatePolyn(){ LinkPolyn head,p,tail; float x; //存储输入的系数 int e; //存储输入的指数 head = (LinkPolyn)malloc(sizeof(Polyn)); //生成头结点 head->next = NULL; //生成空表 tail = head; scanf("%d,%d",&x,&e); while(x!=0) //当x=0时,多项式输入结束 { p = (LinkPolyn)malloc(sizeof(Polyn)); p->xi_shu = x; p->zhi_shu = e; tail->next = p; //在表尾进行插入操作 tail = p; //tail始终指向表尾 scanf("%f,%d",&x,&e); } tail->next = NULL; //将表中最后一个结点的next置为NULl return head; }
二、输出多项式
-
从单链表第一个元素开始,逐项读出系数和指数,按多项式的形式进行输出即可。
/*打印多项式*/ void PrintPolyn(LinkPolyn LA) { LinkPolyn p = LA->next; //LA有头结点,让p指向LA的第一元素结点 int flag = 1; if(!p) //如果链表为空,没有项 { putchar('0'); printf("\n"); //return; } while(p) { if(p->xi_shu > 0 && flag != 1) putchar('+'); //if(p->xi_shu == 0) continue; if(p->xi_shu != 1 && p->xi_shu != -1 && p->xi_shu != 0) { printf("%d",p->xi_shu); if(p->zhi_shu == 1) { putchar('X'); } else if(p->zhi_shu) { printf("X^%d",p->zhi_shu); } else /*系数为1或系数为-1的情况*/ { if(p->xi_shu == 1) { //如果指数为0 if(!p->zhi_shu) putchar('1'); else if(p->zhi_shu == 1) putchar('X'); else printf("X^%d",p->zhi_shu); } if(p->xi_shu == -1) { //如果指数为0 if(!p->zhi_shu) printf("-1"); else if(p->zhi_shu == 1) printf("-X"); else printf("-X^%d",p->zhi_shu); } } p = p->next; flag++; } else{ p = p->next; } } printf("\n"); }
三、两个多项式相加
-
以单链表LA和LB分别表示两个一元多项式A和B,A+B的求和运算就等同于单链表的插入,设一个单链表LC来存放LA+LB的和。
/*两个多项式相加------返回的还是一个多项式*/ LinkPolyn AddPolyn(LinkPolyn LA,LinkPolyn LB) { LinkPolyn pa = LA->next; //指向LA的第一元素结点 LinkPolyn pb = LB->next; //指向LB的第一元素结点 LinkPolyn LC,pc,qc; //LC存储LA+LB pc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi)); pc->next = NULL; LC = pc; //保留原链的头指针 //当两个多项式均未扫描结束时 while(pa != NULL && pb != NULL) { qc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi)); if(pa->zhi_shu < pb->zhi_shu) { qc->xi_shu = pa->xi_shu; qc->zhi_shu = pa->zhi_shu; pa = pa->next; } else if(pa->zhi_shu == pb->zhi_shu) { qc->xi_shu = pa->xi_shu + pb->xi_shu; qc->zhi_shu = pa->zhi_shu; pa = pa->next; pb = pb->next; } else { qc->xi_shu = pb->xi_shu; qc->zhi_shu = pb->zhi_shu; pb = pb->next; } if(qc->xi_shu != 0) { qc->next = pc->next; pc->next = qc; pc = qc; } else free(qc); } /*如果LA中有余项,将剩余项插入LC*/ while(pa != NULL) { qc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi)); qc->xi_shu = pa->xi_shu; qc->zhi_shu = pa->zhi_shu; pa = pa->next; qc->next = pc->next; pc->next = qc; pc = qc; } /*如果LB中有余项,将剩余项插入LC*/ while(pb!= NULL) { qc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi)); qc->xi_shu = pb->xi_shu; qc->zhi_shu = pb->zhi_shu; pb = pb->next; qc->next = pc->next; pc->next = qc; pc = qc; } return LC; }
四、两个多项式相减
-
将减数LB多项式的所有系数变为其相反数,然后使用两个多项式相加的思想进行处理。
/*两个多项式相减------返回的还是一个多项式*/ LinkPolyn SubstractPolyn(LinkPolyn LA,LinkPolyn LB) { LinkPolyn b = LB; LinkPolyn p = LB->next; LinkPolyn LD; while(p) { p->xi_shu *= -1; p = p->next; } LD = AddPolyn(LA,b); for(p = b->next; p ;p = p->next) { p->xi_shu *= -1; } return LD; }
五、多项式乘法
-
多项式乘法类似于两个多项式相加,需要使用一个多项式的每一项和另一个多项式的每一项进行相乘,然后进行多项式相加操作
/*多项式相乘*/ LinkPolyn MultiplyPolyn(LinkPolyn LA,LinkPolyn LB) { LinkPolyn pa = LA->next; LinkPolyn pb = LB->next; LinkPolyn LC,pc,qc; LinkPolyn LD; LD = (LinkPolyn)malloc(sizeof(Polyn)); LD->next = NULL; //建立一个空表 while(pa != NULL) { pc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi)); pc->next = NULL; LC = pc; while(pb != NULL) { qc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi)); qc->xi_shu = pa->xi_shu * pb->xi_shu; qc->zhi_shu = pa->zhi_shu + pb->zhi_shu; qc->next = pc->next; pc->next = qc; pc = qc; pb = pb->next; } LD = AddPolyn(LD,LC); pa = pa->next; pb = LB->next; } return LD; }
六、求多项式的值
-
需要输入变量x的值,然后进行求值运算
/*多项式求值*/ int EvaluatePolyn(LinkPolyn polyn,int x) { LinkPolyn p = polyn->next; int sum = 0; while(p != 0) { sum += p->xi_shu*pow(x,p->zhi_shu); p = p->next; } return sum; }
七、多项式的导数
-
需要根据导数公式对多项式的每一个结点求导,具体过程如下:多项式的当前结点指数为0,则其导数为0;当前结点指数不为0,则其导数的系数为当前结点指数乘以系数,指数为当前结点的指数减1。
/*多项式的导数,返回值仍然为一个多项式*/ LinkPolyn DaoPolyn(LinkPolyn polyn) { LinkPolyn dao = polyn; LinkPolyn p = polyn->next; while(p!=NULL) { if(p->zhi_shu != 0) { p->xi_shu = p->zhi_shu * p->xi_shu; p->zhi_shu = p->zhi_shu - 1; p = p->next; } else { p->xi_shu = 0; p = p->next; } } return dao; }