题目要求
设计函数分别求两个一元多项式的乘积与和。
- 输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。 - 输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。 - 输入样例:
4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1 - 输出样例:
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0
基于c语言,采用链表操作对此题目进行求解。
写出来还是能够增加印象与领悟的。话不多说,show code。
(一)建立程序总体框架
int main(){
Polynomia P1,P2,PP,PS;//建立四个指向结构体的指针变量,分别用于多项式的读取和
P1=ReadPoly();//读入多项式1
P2=ReadPoly();
PP=Mult(P1,P2);//两多项式相乘
PrintPoly(PP);
PS=Add(P1,P2);
PrintPoly(PS);
return 0;
}
将PP和PS分别作为两个多项式(以链表形式存储)相乘和相加得到结果多项式的头节点的指针。
(二)链表的设计
typedef struct PolyNode *Polynomia;//Polynomia的指针变量指向该链表
struct PolyNode{
int coef;//表示多项式的系数
int expon;//表示多项式的指数
Polynomia link;//后一个节点的地址
};
(三) 读入多项式的函数
Polynomia ReadPoly()
{
Polynomia P,Rear,t;//指针初始化
int c,e,N;//变量初始化
scanf("%d",&N);//读入多项式中非零项的个数
P=(Polynomia)malloc(sizeof(struct PolyNode));//申请一个空节点
P->link=NULL;//使节点P的后一个地址为空
Rear=P;//Rear记录尾节点,先把P赋值给Rear
while(N--){
scanf("%d %d",&c,&e);//c,e分别存储读入某一项的系数和指数
Attach(c,e,&Rear);//将c,e所在节点附在当前的Rear指向节点,同时Rear指向当前链表的最后一个节点
}
t=P;P=P->link;free(t);//删除头节点(空)
return P;//P指向当前链表的首节点
}
(四) 将某节点附在Rear后面的Attach函数
void Attach(int c,int e,Polynomia *pRear)//pRear为指针的指针,目的就是在Attach函数调用时,改变实参的地址,这样在此函数所作的操作,才能把Rear附上新的节点
{ Polynomia P;
P=(Polynomia)malloc(sizeof(struct PolyNode));//P作为添加节点临时节点
P->coef=c;
P->expon=e;
P->link=NULL;
(*pRear)->link=P;
(*pRear)=P;//新的节点由pRear指向,同时pRear也是最后一个节点。
}
(五) 两个多项式的分别一项进行相加
Polynomia Add(Polynomia P1,Polynomia P2)
{ Polynomia Rear,P,temp
P=(Polynomia)malloc(sizeof(struct PolyNode));P->link=NULL;
Rear=P;//申请节点的一套标准操作,不再赘述
int sum=0;//作为两个系数相加的和
while(P1&&P2)
{
switch(compare(P1->expon,P2->expon)){//比较P1指向节点与P2指向节点的指数大小
case 1: //P1指数大
Attach(P1->coef,P1->expon,&Rear);//P1接在当前节点上
P1=P1->link;
break;
case -1: //P2指数大
Attach(P2->coef,P2->expon,&Rear);
P2=P2->link;
break;
case 0:
sum=P1->coef+P2->coef;
if(sum){ //两项相加,系数不为零
Attach(sum,P1->expon,&Rear);
P1=P1->link;
P2=P2->link;
break;
}
else{
break;
}
}
}
//当有一个多项式已经没有项数时
while(P1){ //将剩余的P1项附在当前多项式后面
Attach(P1->coef,P1->expon,&Rear);
P1=P1->link;
}
while(P2){
Attach(P2->coef,P2->expon,&Rear);
P2=P2->link;
}
//Rear->link=NULL;
temp=P;
P=P->link;
free(temp);
return P;//temp作为零时节点,存储P(起初设置的空节点),将P指向多项式的首节点(非空),返回此多项式的头结点P
}
一开始在将P1和P2两项相加的时候,反复用if else不见效,遂转变思想,用switch方法,分别处理两者指数比较情况的三种情况,代码更加简洁清楚。compare函数比较简单,就不在此处写了,三种情况返回三种不同的整数。
(六) 两项相乘
Polynomia Mult(Polynomia P1,Polynomia P2)
{
Polynomia P,Rear,t1,t2,t;
P=(Polynomia)malloc(sizeof(struct PolyNode));
P->link=NULL;
int c,e;
Rear=P;
if(!P1||!P2){ //两个多项式都不能为空,再进行计算
return NULL;}
t1=P1;t2=P2; //分别用t1和t2记录两个多项式的头结点
while(t2){ //固定t1,将t2依次后移,计算第一个多项式的第一项乘以第二个多项式的每一项,得到一个初始的多项式
Attach(t1->coef*t2->coef,t1->expon+t2->expon,&Rear);
t2=t2->link;
}
t1=t1->link;
while(t1){
t2=P2;Rear=P;
while(t2){//从第一个多项式的第二项开始,分别乘以第二个多项式的所有项
e=t1->expon+t2->expon;
c=t1->coef*t2->coef;//下面开始把每一项插入当前得到的多项式
while(Rear->link&&Rear->link->expon>e)
Rear=Rear->link;//Rear指数大于待插入节点的指数,Rear后移
if(Rear->link&&Rear->link->expon==e){
if(Rear->link->coef+c)
Rear->link->coef+=c;//如果rear后面指数和待插入相等,插入以后,rear在插入之前
else{
t=Rear->link;
Rear->link=t->link;
free(t);//系数相加为0,rear+t(系数相加为0)+rear->link
}
}
else{//待插入的节点指数在Rear和Rear->link之间,则插入在这两者之间
t=(Polynomia)malloc(sizeof(struct PolyNode));//t->link=NULL;
t->coef=c;t->expon=e;
t->link=Rear->link;
Rear->link=t;
Rear=Rear->link;//Rear表示当前插入节点所在链表的位置
}
t2=t2->link;
}
t1=t1->link;
}
t2=P;P=P->link;free(t2);
return P;//返回相乘完链表的头结点
}
最后,输出函数:
void PrintPoly(Polynomia P)
{
if(!P){printf("0 0\n");return;}
int flag=0;//设置标志位
while(P){
if(!flag)
flag=1;
else
printf(" ");
printf("%d %d",P->coef,P->expon);
P=P->link;
}
printf("\n");
}
这里输出的格式是先不输出空格,后面每次输出系数,指数后有空格。便以空格,系数,指数为一个单位,将得到的多项式从第一个节点遍历到最后一个即可。一开始的标志位,使得第一组没有空格,可以说是还算巧妙了,也自此积累了一个输出格式的方法。