问题描述
题目来源:PTA 数据结构与算法题目集(中文)7-2 一元多项式的乘法与加法运算 (20 分)
一、程序结果
二、实现步骤与程序说明
1.问题分析
题目涉及稀疏多项式的运算,相较于顺序存储结构,采用链式存储结构更为灵活。
对应的数据结构定义为(同严蔚敏教材):
typedef struct PNode{
int coef;
int expn;
struct PNode *next;
}PNode, *Polynomial;
问题可拆分为:多项式的创建,多项式加法,多项式乘法,以及多项式的输出四个步骤,其中多项式的加法与乘法也可理解为和多项式与乘积多项式的创建过程,即前三个过程实现是相似的:
空
链
表
⇒
获
取
c
o
e
f
、
e
x
p
n
进
行
插
入
多
项
式
空链表\xRightarrow{获取coef、expn进行插入}多项式
空链表获取coef、expn进行插入多项式
因此,上述链表插入函数的实现是关键。
2.代码结构
主函数:
void Insert(int a,int e,Polynomial *P); //链表的插入
void CreatePolyn(Polynomial *P); //多项式的创建
Polynomial AddPolyn(const Polynomial P,const Polynomial Q);//多项式加法
Polynomial MultiPolyn(const Polynomial P,const Polynomial Q);//多项式乘法
void Print(Polynomial P); //多项式的输出
int main(){
Polynomial P,Q,S,M;
CreatePolyn(&P);
CreatePolyn(&Q);
S = AddPolyn(P,Q);
M = MultiPolyn(P,Q);
Print(M);
Print(S);
return 0;
}
链表的插入
函数参数:系数
a
a
a,指数
e
e
e;即将
a
x
e
ax^e
axe插入到多项式
P
P
P中。
考虑到和多项式、乘积多项式的创建存在合并同类项的问题,插入函数分两种情况:
- P P P中存在 x e x^e xe项:合并同类项
- P P P中不存在 x e x^e xe项:按降幂形式插入
具体实现如下:
void Insert(int a,int e,Polynomial *P){
PNode *p,*pre;
pre = (*P);
p = (*P)->next;
int flag = 0;
while(p&&!flag){
//已存在指数等于e的项
if(p->expn==e){
if(p->coef+a==0){
pre->next=p->next;
} //合并后系数为0,删除该项
else{
p->coef = p->coef+a;
} //合并后系数不为0,更新系数
flag = 1;
}
pre = p;
p=p->next;
}
pre = (*P);
p = (*P)->next;
if(!flag){ //不存在指数等于e的项
PNode *s = (Polynomial)malloc(sizeof(PNode));
s->coef = a;
s->expn = e;
s->next = NULL; //创建新结点,系数为a,指数为e
while(p&&(p->expn>s->expn)){
pre = p;
p = p->next;
} //找出首个指数小于e的结点,用pre记录其前驱
s->next = p;
pre->next = s;
}
}
多项式的创建
这里调用Insert()
函数,提高了数据输入的容错率,多项式即便不以降幂形式输入数据,得到的仍然是降幂结果。注:链表包含头结点。
void CreatePolyn(Polynomial *P){
(*P) = (Polynomial)malloc(sizeof(PNode));
(*P)->next = NULL;
int i,n;
scanf("%d",&n);
for(i=0;i<n;i++){
int coef,expn;
scanf("%d%d",&coef,&expn);
Insert(coef,expn,P);
}
}
多项式加法
函数参数:Polynomial P, Polynomial Q
返回类型同样为链表类型。
设置两个指针
p
p
p、
q
q
q分别指向
P
P
P、
Q
Q
Q的首元结点,逐一比较其指数,将指数较大的结点,取其数据插入和多项式中;指数相等,且系数之和不为0,将合并结果插入和多项式。当
p
p
p、
q
q
q中任一为空(NULL),则将另一多项式剩余结点逐一插入和多项式。
Polynomial AddPolyn(const Polynomial P,const Polynomial Q){
Polynomial S = (Polynomial)malloc(sizeof(PNode));
S->next = NULL;
PNode *p,*q;
p = P->next;
q = Q->next;
while(p&&q){
if(p->expn>q->expn){
Insert(p->coef,p->expn,&S);
p = p->next;
}
else if(p->expn<q->expn){
Insert(q->coef,q->expn,&S);
q = q->next;
}
else{
if(p->coef+q->coef!=0){
Insert(p->coef+q->coef,q->expn,&S);
}
p = p->next;
q = q->next;
}
}
while(p){
Insert(p->coef,p->expn,&S);
p = p->next;
}
while(q){
Insert(q->coef,q->expn,&S);
q = q->next;
}
return S;
}
多项式乘法
函数参数:Polynomial P, Polynomial Q
返回类型同样为链表类型。
设置两个指针
p
p
p、
q
q
q分别指向
P
P
P、
Q
Q
Q的首元结点,通过二重循环得到乘积多项式未合并前的每一项,逐项插入。
Polynomial MultiPolyn(const Polynomial P,const Polynomial Q){
Polynomial S = (Polynomial)malloc(sizeof(PNode));
S->next = NULL;
PNode *p,*q;
p = P->next;
q = Q->next;
while(p){
while(q){
Insert(p->coef*q->coef,p->expn+q->expn,&S);
q = q->next;
}
q = Q->next;
p = p->next;
}
return S;
}
多项式的输出
按照题目要求,零多项式输出:0 0
,最后一项结果后不含空格
。
void Print(Polynomial P){
PNode *p;
p = P->next;
int flag = 0;
if(!p){
printf("0 0");
}
while(p){
if(!flag){
flag = 1;
}
else{
printf(" ");
}
printf("%d %d",p->coef,p->expn);
p = p->next;
}
printf("\n");
}
三、总结
多项式乘法或可借助加法函数实现:
M
(
x
)
=
P
(
x
)
×
Q
(
x
)
=
P
(
x
)
×
(
b
1
x
e
1
+
.
.
.
+
b
n
x
e
n
)
=
∑
i
=
1
n
b
i
P
(
x
)
x
e
i
M(x)=P(x)\times Q(x)=P(x)\times (b_1x^{e_1}+...+b_nx^{e_n})=\sum_{i=1}^n b_iP(x)x^{e_i}
M(x)=P(x)×Q(x)=P(x)×(b1xe1+...+bnxen)=i=1∑nbiP(x)xei
即M=AddPolyn(M,P')
这里多项式P'
需要借助上述公式重新生成。