一元多项式的表示及相加
对于符号多项式的各种操作,实际上都可以利用线性表来处理。比较典型的是关于一元多项式的处理。在数学上,一个一元多项式P
n(x)可按升幂的形式写成:Pn(x)=p
0+p
1x+p
2x
2+p
3x
3+…+p
nx
n。它实际上可以由n+1个系数唯一确定。因此,在计算机内,可以用一个线性表P来表示:P=(p
0,p
1,p
2,…,p
n)其中每一项的指数隐含在其系数的序号里了。
假设Q
m(x)是一个一元多项式,则它也可以用一个线性表Q来表示,即Q=(q
0,q
1,q
2,…,q
n)若假设m<n,则两个多项式相加的结果R
n(x)=P
n(x)+Q
m(x),也可以用线性表R来表示:R(p
0+q
0,p
1+q
1,p
2+q
2,,p
m+q
m,p
m+1,…,p
n)。
我们可以采用顺序表存储结构来实现顺序表的方法,使得多项式的相加的算法定义十分简单,即p[0]存系数p
0,p[1]存系数p
1,…,p[n]存系数p
n,对应单元的内容相加即可。但是在通常的应用中,多项式的指数有时可能会很高并且变化很大。例如:R(x)=1+5x
10000+7x
20000
若采用顺序存储,则需要20001个空间,而存储的有用数据只有三个,这无疑是一种浪费。若只存储非零系数项,则必须存储相应的指数信息才行。
假设一元多项式P
n(x)=p
1x
e1+p
2x
e2+…+p
mx
em,其中p
ie
i的项的系数(且0≤e
1≤e
2≤…≤e
m=n),若只存在非零系数,则多项式中每一项有两项构成(指数项和系数项),用线性表来表示,即((p
1,e
1),(p
2,e
2),…,(p
m,e
m))。
采用这样的方法存储,在最坏情况下,即n+1个系数都不为零,则比只存储系数的方法多存储1倍的数据。但对于非零系数多的多项式则不宜采用这种表示。
对与线性表的两种存储结构,一元多项式也有存储表示方法。在实际应用中,可以是具体情况而定。下面将学习到用单链表实现一元多项式相加运算的方法。
(1)用单链表存储多项式的结点结构如下:
typedef struct Polynode
{
int coef;
int exp;
struct Polynode *next;
}Polynoce,*Polylist;
|
(2)通过键盘输入一组多项式的系数和指针,以输入系数0为结束标志,并约定建立多项式链表时,总是按指数从大到小的顺序排列。
算法描述:从键盘接受输入的系数和指针;用尾插法建立一元多项式的链表。
Polylist polycreate()
{
Polynode *head,*rear,8s;
int c,e;
head=(Polynode *)malloc(sizeof(Polynode));/*建立多项式的头结点*/
rear=head;/*rear始终指向单链表的尾,便于尾插法建表*/
scanf("%d,%d",&c,&e);/*键入多项式的系数和指针项*/
while(c!=0)/*若c=0,则代表多项式的输入结束*/
{
s=(Polynode *)malloc(sizeof(Polynode));/*申请新的结点*/
s->coef=c;
s->exp=e;
rear->next=s;/*在当前表尾做插入*/
rear=s;
scanf("%d,%d",&c,&e);
}
rear-next=NULL;/*将表的最后一个结点的nest置NULL,以示结束*/
return (head);
}
算法
用尾插法建立一元多项式的链表
|
图2.19所示为两个多项式的单链表,分别表示多项式A(x)=7+3x+9x
8+5x
17和多项式B(x)=8x+22x
7-9x
8。
多项式相加的运算规则是:两个多项式中所有指数相同的项的对应系数相加,若和不为零,则构成“和多项式”中的一项;所有指数不相同的项均复抄到“和多项式”中。以单链表作为存储结构,并且“和多项式”中的结点无需 生成,则可看成是将多项式B加到多项式A中,由此的到下列运算规则(设p、q分别指向多项式A、B的一项,比较结点的指数项):
若p->exp<q->exp,则结点p所指的结点应是“和多项式”中的一项,令指针p后移;
若p->exp>q->exp,则结点q所指的结点应是“和多项式”中的一项,将结点q插入在结点p之前,且令指针q在原来的链表上后移;
若p->exp=q->exp,则将两个结点中的系数相加,当和不为零时修改结点p的系数域,释放q结点;若和为零,则和多项式中无此项,从A中删去p结点,同时释放p和q结点。
void polyadd(Polylist polya;Polylist polyb)
/*此函数用于将两个多项式相加,然后将和多项式存放在多项式polya中,并将多项式ployb删除*/
{
Polynode *p,*q,*pre,*temp;
int sum;
p=polya->next;/*令p和qfenbie指向polya和polyb多项式链表中的第一个结点*/
q=polyb->next;
pre=polya;/*pre指向和多项式的尾结点*/
while(p!=NULL&&q!=NULL)/*当两个多项式均为扫描结束时*/
{
if(p->exp<q->exp)
/*如果p指向的多项式项的指数小于q的指数,将p结点加入到和多项式中*/
{
pre-next=p;pre=pre->next;
p=p->next;
}
else if(p->exp==q->exp)/*若指数相等,则相应的系数相加*/
{
sum=p->coef+q->coef;
if(sum!=0)
{
p->coef=sum;
pre->next=p;pre=pre->next;
p=p-next;temp=q;q=q->next;free(temp);
}
else
{
temp=p->next;free(p);p=temp;
/*若系数和为零,则删除结点p与q,并将指针指向下一个结点*/
temp=q->next;free(q);q=temp;
}
}
else
{
pre->next=q;pre=pre->next;/*将q结点加入到和多项式中*/
q=q->next;
}
}
if(p!=NULL)/*多项式A中还有剩余,则将剩余的结点加入到和多项式中*/
pre->next=p;
else/*否则,将B中的结点加入到和多项式中*/
pre->next=q;
}
算法
多项式相加
|
假设A多项式有M项,B多项式有N项,则上述算法的时间复杂度为O(M+N)。
图2.20所示为图2.19中两个多项式的和,其中孤立的结点代表被释放的结点。
通过对多项式加法的介绍,我们可以将其推广到实现两个多项式的相乘,因为乘法可以分解为一系列的加法运算。