设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分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
示例代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int x;
int z;
struct Node *next;
}*List;//定义,注意这里的List ==struct Node*,所以后面List定义的都是指针类型,而List *r就是二重指针,相当于struct Node**,作用是指针的传地址的实现
void Attach(int x,int z,List *r);
List InPut();
List GetMul(List p1,List p2);
List GetSum(List P1,List P2);
void OutPut(List p);
int main(){//用函数简单明了
List p1,p2,sum,mul;
p1=InPut();
p2=InPut();
mul=GetMul(p1,p2);
OutPut(mul);
printf("\n");
sum=GetSum(p1,p2);
OutPut(sum);
}
List InPut(){
int n,x,z;
List r,temp,p;
p=(struct Node*)malloc(sizeof(struct Node));//申请一个新的空间用于返回一个链表
// p->next=NULL;//默认就是NULL
r=p;//最后要返回的是链表初始指针,所以用r来当工具参
scanf("%d",&n);
while(n--){
scanf("%d %d",&x,&z);
if(x!=0){
Attach(x,z,&r);//这个函数是在链表后插入新块的函数,用的比较频繁就直接写成函数方便阅读和写
}
}
temp=p;
p=p->next;
free(temp);//这一步是把开头的没有数据的那一节删了free,不然第一节的x,z是空的,有的题目不删
return p;
}
void Attach(int x,int z,List *r){
List p;
p=(struct Node*)malloc(sizeof(struct Node));
p->x=x;
p->z=z;
p->next=NULL;//默认是NULL的
(*r)->next=p;//把创建好的新节点接在我们链表的后面
(*r)=p; //接完了之后,工具参要下移
}
List GetMul(List p1,List p2){
if(!p1||!p2) return NULL;//乘法一方为空直接退出
List r,p,temp,t1,t2;
int x,z;
p=(struct Node*)malloc(sizeof(struct Node));
p->next=NULL;
r=p;
t1=p1;t2=p2;
while(t2){
Attach(t1->x*t2->x,t1->z+t2->z,&r);
t2=t2->next;
}
t1=t1->next;//这里是先把p1的第一个数和最后一个数相乘得到结果,因为只有一次,不用考虑指数插入的问题,这步算是思路推导的步骤,可以完全省略的
//先得到一组数据,再考虑后面的数据如何插入
while(t1){
t2=p2;r=p;//这里每次循环,p2都要从头开始,我们要返还的p也要从头开始检测指数大小,所以需要两个工具参,很关键
while(t2){
x=t1->x*t2->x;
z=t1->z+t2->z;//这里先把系数指数算出来方便后面的计算
while(r->next&&r->next->z>z){
r=r->next;
}//计算当下一项的指数大于待插入项那就直接检查下一项
if(r->next&&r->next->z==z){
if(r->next->x+x){
r->next->x+=x;
}else{
temp=r->next;
r->next=temp->next;
free(temp);
}//当下一项和待插入项指数相等还要考虑系数抵消的情况
}else{
temp=(struct Node*)malloc(sizeof(struct Node));
temp->x =x;temp->z=z;
temp->next=r->next;
r->next=temp;//r=r->next;这里多了一步,我错了然后就抄,抄的时候没细品,复盘发现这句是多的
//找到了待插入的地方就创建一个新的块赋值然后插入,因为是从中间插入的 ,所以先后赋值顺序要缕一缕,先让插入项指向下一个指针,不然链表就断了
}
t2=t2->next;
}
t1=t1->next;
}
temp=p;
p=p->next;
free(temp);
return p;//老套路了,删除链表的头然后free
}
List GetSum(List P1,List P2){
List r,p,temp;
List p1=P1,p2=P2;//为什么多这一步,可有可无啊,别问,问就是好习惯
int x,z;
p=(struct Node*)malloc(sizeof(struct Node));
p->next=NULL;
r=p;//老套路了,可爱的工具参r
while(p1 && p2){
if(p1->z==p2->z){
if(p1->x+p2->x!=0){
Attach(p1->x+p2->x,p1->z,&r);
}
p1=p1->next;
p2=p2->next;
//上面的是系数相等,都要判断指数会不会抵消,然后这里p1和p2要同时下移
}else if(p1->z > p2->z){
Attach(p1->x,p1->z,&r);
p1=p1->next;
}else{
Attach(p2->x,p2->z,&r);
p2=p2->next;
}//正常的赋值
}
while(p1){
Attach(p1->x,p1->z,&r);
p1=p1->next;
}
while(p2){
Attach(p2->x,p2->z,&r);
p2=p2->next;
}
//当一边加完了,就判断没有加完的,这里是一个一个赋值,所以用while,要是链表的有序合并那就用if就行,血的教训嗷
temp=p;
p=p->next;
free(temp);
return p;
}
void OutPut(List p){
int flag=0;//flag挺好用的,下面的if(!flag)就是让第一次不执行,后续的都执行,题目要求最后没有空格的,flag解决
if(!p) printf("0 0");
while(p){
if(!flag){
flag=1;
}else{
printf(" ");
}
printf("%d %d",p->x ,p->z );
p=p->next;
}
}