一元多项式:
可以用一个线性表P来表示:
Pn(x)线性表表示法每一项的指数从系数下标即可表示
1.采用顺序存储结构来存系数,对应单元的内容相加即可。
但在通常的应用中,多项式的指数有时可能会变化很高并且变化很大,如下图
用一长度为20001的线性表来表示,表中仅有3个非零元素,浪费空间。所以我们可以存储非零系数项和相应的指数。
假设一元多项式:
线性表表示:只存非零系数,多项式中每一项由指数项和系数项构成。用单链表实现。
1.结构描述
结点包含两个数据域:一个是系数coef,另一个是指数exp。
多项式结点结构:
typedef struct Polynode
{
int coef; //系数
int exp; // 指数
Polynode *next;
} LinkListNode;
2.算法描述
对所有指数相同的项,将其对应系数相加,若和不为零,则构成和多项式中的一项;
将所有指数不相同的项复制到和多项式中。
和多项式采用形式:
方法一:新建
方法二:把一个多项式归并入另一个多项式
多项式 2 + 3X + 5X^3 + 2X ^4 与 3 + 2X + 4X ^2 相加
1)方法一
/*
函数功能:将两个多项式polyA和polyB相加,然后将和多项式存放在多项式polyC中。
函数输入:polyA和polyB链的首地址
函数输出:polyC链地址
*/
伪代码描述:
设pa指向headA链、pb指向headB链
while (pa、pb两个链都没处理完)
{
if (pa、pb指向当前结点的指数项相同)
{
系数相加,当和不为零时在C链中添加新的结点;
pa、pb指针后移一位;
}
else
{
以指数小的项的系数添入C链中的新结点;
指数小的相应链指针后移;
}
}
p指向未处理完的链
while( p非空)
{ 顺序处理p链;}
程序实现:
#include<stdio.h>
#include<malloc.h>
#define ElemType int
typedef struct Polynode
{
int coef; //系数
int exp; // 指数
Polynode *next;
} LinkListNode;
LinkListNode *attach(ElemType c, int e, LinkListNode* pc);
/*=====================================================
函数功能:将两个多项式polyA和polyB相加,然后将和多项式存放在多项式polyC中。
函数输入:polyA和polyB链的首地址
函数输出:polyC链地址
======================================================*/
LinkListNode *polyadd_headC(LinkListNode *headA, LinkListNode *headB)
{
LinkListNode *headC;
LinkListNode *pa, *pb, *pc, *p;
ElemType x;
pa=headA->next;
pb=headB->next;
headC=(LinkListNode*)malloc(sizeof(LinkListNode));
pc=headC;
while(pa&&pb)
{
if(pa->exp==pb->exp)
{
x=pa->coef+pb->coef;
if(x!=0) pc=attach(x,pa->exp,pc);
pa=pa->next;
pb=pb->next;
continue;
}
if(pa->exp < pb->exp)
{p=pa;
pa=pa->next;
}
else
{p=pb;
pb=pb->next;
}
pc=attach(p->coef,p->exp,pc);
}
p=pa;
if(pa==NULL) p=pb;
while(p)
{
pc=attach(p->coef,p->exp,pc);
p=p->next;
}
pc->next=NULL;
return headC;
}
/*=====================================================
函数功能:建立系数为c,指数为e的新结点,并把它插在
pc所指结点的后面,链接后pc指向新链入的结点
函数输入:系数c,指数e,pc地址
函数输出:pc地址
======================================================*/
LinkListNode *attach(ElemType c, int e, LinkListNode* pc)
{
LinkListNode *p;
p=(LinkListNode *)malloc(sizeof(LinkListNode));
p->coef=c;
p->exp=e;
pc->next=p;
return p;
}
2)方法二:
将两个多项式polyA和polyB相加,然后将和多项式存放在多项式polyA中,并将多项式ployB删除。
/==================================================
函数功能: 将两个多项式polyA和polyB相加,结果存放在polyA中
函数输入:polyA和polyB链首地址
函数输出:无
====================================================/
伪代码如下:
设pa指向headA链、pb指向headB链
while (pa、pb两个链都没处理完)
{
if (pa、pb指向当前结点的指数项相同)
{ 两个结点中的系数相加;
当和不为零时修改结点pa的系数域,释放pb结点;
若和为零,则和多项式中无此项,删去pa结点,同时释放pa和pb结点。
continue;
}
if (pa指数小于pb指数)
{ pa结点应是“和多项式”中的一项,pa后移;
continue;
}
if (pa指数大于pb指数)
{ pb结点应是“和多项式”中的一项,将pb插入在pa之前,
pb后移;
continue;
}
}
若pb非空,将其加入pa链尾。
程序实现:
/*==================================================
函数功能: 将两个多项式polyA和polyB相加,结果存放在polyA中
函数输入:polyA和polyB链首地址
函数输出:无
====================================================*/
void polyadd_headA(LinkListNode *polyA, LinkListNode *polyB)
{
LinkListNode *pa, *pb, *pre, *temp;
int sum;
//令 pa 和 pb 分别指向polyA 和 polyB 多项式链表中的第一个结点
pa=polyA->next;
pb=polyB->next;
pre=polyA; //pre 指向和多项式的尾结点
while(pa!=NULL&&pb!=NULL) //当两个多项式均未扫描结束时
{
if(pa->exp==pb->exp) //若指数相等
{
sum=pa->coef+pb->coef; //相应的系数相加
if(sum!=0) //若系数和非零
{
pa->coef=sum;
pre->next=pa;
pre=pre->next;
pa=pa->next;
temp=pb;
pb=pb->next;
free(temp);
continue;
}
else //若系数和为零
{
temp=pa->next;
free(pa);
pa=temp;
temp=pb->next;
free(pb);
pb=temp;
continue;
}
}
if(pa->exp<pb->exp) //pa的指数大于pb的指数
//pa与pre指针后移
{
pre->next=pa;
pre=pre->next;
pa=pa->next;
continue;
}
if(pa->exp>pb->exp) //pa的指数小于pb的指数
//将pb结点加入到pa前
{
pre->next=pb;
pre=pre->next;
pb=pb->next;
pre->next=pa;
continue;
}
}
if(pb!=NULL) //将剩余的pb加入到和多项式中
pre->next=pb;
}
/*==================================================
函数功能: 用尾插法建立一元多项式的链表
函数输入:多项式系数与指数数组、多项式项数
函数输出:多项式链表首地址
====================================================*/
LinkListNode *CreateList_Rear(ElemType a[][2], int n)
{
LinkListNode *head, *p, *q;
int i;
head=(LinkListNode *)malloc(sizeof(LinkListNode));
q=head;
for(i=0; i<n; i++)
{
p=(LinkListNode *)malloc(sizeof(LinkListNode));
p->coef=a[i][0];
p->exp=a[i][1];
q->next=p;
q=p;
}
p->next=NULL;
return head;
}
3.程序测试
#include<stdio.h>
#include<malloc.h>
LinkListNode *CreateList_Rear(ElemType a[][2], int n);
LinkListNode *polyadd_headC(LinkListNode *polyA, LinkListNode *polyB);
LinkListNode *attach(ElemType c, int e, LinkListNode *polyB);
void polyadd_headA(LinkListNode *polyA, LinkListNode *polyB);
void PrintList(LinkListNode *L);
int main()
{
int a[][2]={{3,14},{2,8},{1,6}};
int b[][2]={{8,14},{-3,10},{10,6},{1,0}};
LinkListNode *headA, *headB;
LinkListNode *linkPtr;
headA=CreateList_Rear(a,3);
headB=CreateList_Rear(b,4);
linkPtr=polyadd_headC(headA,headB);
printf("另建多项式保存时:\n");
PrintList(linkPtr);
polyadd_headA(headA,headB);
printf("将和多项式保存A中时:\n") ;
PrintList(headA);
return 0;
}
void PrintList(LinkListNode *L)
{
LinkListNode *p;
p=L->next;//跳出头结点
int i=1;
while(p)//链表为空
{
printf("第%d项系数是%d,次方是%d\n",i,p->coef,p->exp);
i++;
p=p->next;
}
}
测试结果:结果显然输出不对,不过没找到错误。
以后再说吧
小结:处于初学阶段,相比以前觉得索然无味,现在感觉算是一个个小挑战,不断学习,提高代码水平。越往后学习要更快、更有质量、更要坚持。
附:顺序表和链表的比较
顺序存储
优点:
方法简单,容易实现。
无额外的存储开销。
随机存取,简洁便利。
缺点:
插入删除操作运算效率低。
需要预先分配足够大的存储空间,估计过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。
链式存储主要优点
无需事先了解线性表的长度。
允许线性表的长度有很大变化。
能够适应经常插入、删除内部元素的情况。
通过建立双向或循环链表提高访问效率
线性表存储结构的选用考量