问题描述
问题如题目所示。
存储结构
- 因为多项式的长度是不确定的,所以采用链表形式更加方便。
- 多项式的每一项都包括一个系数和指数,所以需要自定义每一项的数据结构。
- 由于在加法和减法操作中,有序的链表结构更加方便,所以可以创建有序链表。这里采用的方法是要求输入时就为指数递减输入(乱序输入,程序来排序的创建函数,后面会考虑补上)
//一元多项式项的表示
typedef struct{
float c; //系数
int e; //指数
}ElemType;
//链表结构
typedef struct SLNode
{
ElemType val;
struct SLNode *next;
}node, *LinkList;
基本操作
关于多项式的基本操作:
//建立有序链表
void CreatPoly(LinkList &P, int m);
//销毁一元多项式
void DestoryPoly(LinkList &P);
//打印输出一元多项式
void PrintPoly(LinkList P);
//返回一元多项式P中的项数
int PolyLength(LinkList P);
//多项式相加
void AddPoly(LinkList &Pa, LinkList &Pb, LinkList &Pc);
//多项式相减
void SubtractPoly(LinkList &Pa, LinkList &Pb, LinkList &Pc);
关于链表的基本操作:https://blog.csdn.net/qq_41856633/article/details/98873635
其中有一些改动,增加了一个函数:
//返回满足cmp的元素的索引
int getIndex(LinkList L, ElemType e, int (* compare)(ElemType, ElemType))
{
LinkList p = L->next;
int i = 1;
while(p){
if(compare(e, p->val) == 0) return i;
i ++;
p = p->next;
}
return i;
}
实现
- 初始化
//建立有序链表
void CreatPoly(LinkList &P, int m)
{
Init_List(P);
printf("请依次输入每一项的系数和指数,以空格区分。\n");
for(int i = 0; i < m; i ++){
ElemType data;
scanf("%f %d", &data.c, &data.e);
int index = getIndex(P, data, cmp);
if(index <= PolyLength(P)){ //指数相同进行合并
LinkList q = P;
while(index -- ) q = q->next;
q->val.c += data.c;
continue;
}
bool flag = addElem(P, i + 1, data);
if(!flag) return;
}
}
在添加的时候,如果两次输入同一指数的项会进行合并。
- 打印多项式
//打印输出一元多项式
void PrintPoly(LinkList P)
{
int length = PolyLength(P);
for(int i = 0; i < length - 1; i++){
ElemType data;
getElem(P, i+1, data);
printf("%.2fx^%d + ", data.c, data.e);
}
ElemType data;
getElem(P, length, data);
printf("%.2fx^%d\n", data.c, data.e);
}
这里,指数为0没有进行处理。(可以尝试在指数为0时只输出系数)
- 相加
//多项式相加
void AddPoly(LinkList &Pa, LinkList &Pb, LinkList &Pc)
{
LinkList qa = Pa->next;
LinkList qb = Pb->next;
Init_List(Pc);
LinkList qc = Pc;
while(qa && qc){
ElemType dataa = qa->val;
ElemType datab = qb->val;
if(dataa.e > datab.e){
qc->next = qa;
qa = qa->next;
}else if(dataa.e < datab.e){
qc->next = qb;
qb = qb->next;
}else{
dataa.c += datab.c;
if(dataa.c == 0){ //系数为0就直接删除结点
LinkList s = qa;
qa = qa->next;
free(s);
s = qb;
qb = qb->next;
free(s);
continue;
}
qa->val.c = dataa.c;
qc->next = qa;
LinkList s = qb;
qb = qb->next;
qa = qa->next;
free(s);
}
qc = qc->next;
}
if(qa){
qc->next = qa;
}
if(qb){
qc->next = qb;
}
free(Pa);
free(Pb);
}
这里为了节约空间,只声明了一个新的Pc头结点,其他均用以有的结点进行连接。(运算完成后可以删除Pa和Pb的头结点).
介于减法就是Pb每一项乘以 -1 再和Pa相加,就不再写了。
小结
大致的基本操作就是这样(乘法相对比较繁琐,并且也是以加法为基础的,就没有写了。貌似没有看到乘法的考试要求,就不为难自己了…)
完整代码地址