PTA 7-2 一元多项式的乘法与加法运算
1. 题目
设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分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
2. 分析
-
这里选用普通的线性表存储多项式。
-
这里我们先定义一个线性表
typedef struct Item{ int f,l; }Item; typedef int Pos; typedef struct LNode{ enum{Max=1001}; Item Data[Max]; Pos Last; }LNode; typedef struct LNode* List;
由于题干已经给出指数不会超过1000,所以我们可以直接定义一个1001大小的数组。Item储存的是每项的系数和指数。
-
对应的操作有:
-
创建一个线性表
List Create(){ List L=(List)malloc(sizeof(LNode)); L->Last=-1; return L; }
-
在线性表的指定位置插入元素
void Insert(List L,Item I,Pos P){ if(L->Last==Max-1){ printf("FULL\n"); return; } if(P<0||P>L->Last+1){ printf("WRONG POS\n"); return; } for(int i=L->Last;i>=P;i--){ L->Data[i+1]=L->Data[i]; } L->Data[P]=I; L->Last++; }
-
打印线性表
void Print(List L){ int mark=1; for(int i=0;i<=L->Last;i++){ printf("%d %d",L->Data[i].f,L->Data[i].l); if(i!=L->Last) printf(" "); mark=0; } if(mark) printf("0 0"); }
- 这里需要注意的是输出的格式,以及零多项式(各项系数均为0)的处理
-
销毁线性表
void Destory(List L){ free(L); }
-
-
多项式相加操作
List CalAdd(List L1,List L2){ List L=Create(); int i1=0; int i2=0; Item item; while(i1<=L1->Last&&i2<=L2->Last){ if(L1->Data[i1].l==L2->Data[i2].l){ item.f=L1->Data[i1].f+L2->Data[i2].f; item.l=L1->Data[i1].l; if(item.f){ Insert(L,item,L->Last+1); } ++i1; ++i2; } else{ int l1=L1->Data[i1].l; int l2=L2->Data[i2].l; item.l=l1>l2?l1:l2; item.f=l1>l2?L1->Data[i1].f:L2->Data[i2].f; Insert(L,item,L->Last+1); if(l1>l2) ++i1; else ++i2; } } int begin= i1>L1->Last?i2:i1;//注意取值的条件判断越界 int end= i1>L1->Last?L2->Last:L1->Last; List LL= i1>L1->Last?L2:L1; for(int i=begin;i<=end;i++){ Insert(L,LL->Data[i],L->Last+1); } return L; }
- 多项式的相加操作,其实就是合并两个线性表。如果有相同指数的项,则将系数相加,如果系数相加之后为0,则将这一项省略。
- 最简单的做法就是遍历这两个线性表,时间复杂度为O(n^2),这显然不是我们想要的结果。
- 那能不能通过一次遍历就将这个线性表合并呢?当然可以。首先定义两个指针(其实是数组的指数index,类型为int),分别指向两个线性表的表头。如果两个指针指向的数据指数相同,就将它们系数进行相加,送入新的线性表中(Insert操作),同时将两个指针向后移一位。如果指向的数据不同,取指数较大的数据送入新的线性表,同时它的指针向后移一位,另一个指针不动。重复这个操作,直到一个线性表遍历结束。然后将有剩余的那个线性表的剩余数据送入新线性表中(当然也可能两个都无剩余)。
-
多项式相乘操作
List CalMulti(List L1,List L2){ List temp=Create(); Item item; List L=Create(); for(int i=0;i<=L1->Last;i++){ for(int j=0;j<=L2->Last;j++){ item.f=L1->Data[i].f*L2->Data[j].f; item.l=L1->Data[i].l+L2->Data[j].l; Insert(temp,item,temp->Last+1); } List p=L; L=CalAdd(L,temp); Destory(p); temp->Last=-1; / } Destory(temp); return L; }
- 多项式的相乘操作即对一个多项式的每一项乘以另一个多项式的每一项,然后将结果相加。时间复杂度O(n^2),没有想到更好的解法,有更好解决办法的小伙伴可以留言,一起学习交流。
3. 全部代码
#include<stdio.h>
typedef struct Item{
int f,l;
}Item;
typedef int Pos;
typedef struct LNode{
enum{Max=1001};
Item Data[Max];
Pos Last;
}LNode;
typedef struct LNode* List;
List Create(){
List L=(List)malloc(sizeof(LNode));
L->Last=-1;
return L;
}
void Destory(List L){
free(L);
}
void Insert(List L,Item I,Pos P){
if(L->Last==Max-1){
printf("FULL\n");
return;
}
if(P<0||P>L->Last+1){
printf("WRONG POS\n");
return;
}
for(int i=L->Last;i>=P;i--){
L->Data[i+1]=L->Data[i];
}
L->Data[P]=I;
L->Last++;
}
void Print(List L){
int mark=1;
for(int i=0;i<=L->Last;i++){
printf("%d %d",L->Data[i].f,L->Data[i].l);
if(i!=L->Last) printf(" ");
mark=0;
}
if(mark) printf("0 0");
}
List CalAdd(List L1,List L2){
List L=Create();
int i1=0;
int i2=0;
Item item;
while(i1<=L1->Last&&i2<=L2->Last){
if(L1->Data[i1].l==L2->Data[i2].l){
item.f=L1->Data[i1].f+L2->Data[i2].f;
item.l=L1->Data[i1].l;
if(item.f){
Insert(L,item,L->Last+1);
}
++i1;
++i2;
}
else{
int l1=L1->Data[i1].l;
int l2=L2->Data[i2].l;
item.l=l1>l2?l1:l2;
item.f=l1>l2?L1->Data[i1].f:L2->Data[i2].f;
Insert(L,item,L->Last+1);
//if(l1>l2) ++i1;
// else ++i2;
l1>l2? ++i1:++i2;
}
}
int begin= i1>L1->Last?i2:i1;//注意取值的条件判断越界
int end= i1>L1->Last?L2->Last:L1->Last;
List LL= i1>L1->Last?L2:L1;
for(int i=begin;i<=end;i++){
Insert(L,LL->Data[i],L->Last+1);
}
return L;
}
List CalMulti(List L1,List L2){
List temp=Create();
Item item;
List L=Create();
for(int i=0;i<=L1->Last;i++){
for(int j=0;j<=L2->Last;j++){
item.f=L1->Data[i].f*L2->Data[j].f;
item.l=L1->Data[i].l+L2->Data[j].l;
Insert(temp,item,temp->Last+1);
}
List p=L;
L=CalAdd(L,temp);
Destory(p);
temp->Last=-1;
}
Destory(temp);
return L;
}
int main(){
int cnt;
Item t;
List L1=Create();
List L2=Create();
scanf("%d",&cnt);
for(int i=0;i<cnt;i++){
scanf("%d%d",&t.f,&t.l);
Insert(L1,t,L1->Last+1);
}
scanf("%d",&cnt);
for(int i=0;i<cnt;i++){
scanf("%d%d",&t.f,&t.l);
Insert(L2,t,L2->Last+1);
}
List L3=CalAdd(L1,L2);
List L4=CalMulti(L1,L2);
Print(L4);
printf("\n");
Print(L3);
Destory(L1);
Destory(L2);
Destory(L3);
Destory(L4);
}