题目描述
编写一元多项式加法运算程序。要求用线性链表存储一元多项式(参照课本)。
输入:输入三个多项式,建立三个多项式链表Pa、Pb、Pc(提示:调用CreatePolyn(polynomial &P,int m)。输入格式要求如下所示:
1
多项式A包含的项数,以指数递增的顺序输入多项式A各项的系数(整数)、指数(整数)
多项式B包含的项数,以指数递增的顺序输入多项式B各项的系数(整数)、指数(整数)
多项式C包含的项数,以指数递增的顺序输入多项式C各项的系数(整数)、指数(整数)
0 ---操作终止,退出。
输出:显示三个输入多项式Pa、Pb、Pc、和多项式Pa+Pb、多项式Pa+Pb+Pc(提示:调用AddPolyn(polynomial &Pa, polynomial Pb), 调用PrintPolyn(polynomial P))。
多项式输出格式:以指数递增的顺序输出: <系数,指数>,<系数,指数>,<系数,指数>。零多项式的输出格式为<0,0>。
解题思路
该题用链表来储存多项式的项,首先要弄清表达形式:
这里使用系数、指数的形式来连续储存,并且构造出题目要求的函数实现的功能。
typedef struct TERM* ptr;
struct TERM {
int Coefficient;
int Exponent;
ptr Next;
};
typedef ptr Polynomial;
void CreatePolyn(Polynomial P, int m);
Polynomial AddPolyn(Polynomial Pa, Polynomial Pb);
void PrintPolyn(Polynomial P);
下一步是构造多项式(CreatePolyn()):
m表示多项式项数,表示多项式头结点为空(第一项为下一项)。本题多项式都是按照指数递增的形式,所以不用调序。
void CreatePolyn(Polynomial P, int m)
{
ptr cur = P->Next = (ptr)malloc(sizeof(struct TERM));
for (int n = 0; n < m; n++)
{
int coef, comp;
cin >> coef >> comp;
cur->Coefficient = coef;
cur->Exponent = comp;
if (n == m - 1)
cur->Next = NULL;
else
{
cur->Next = (ptr)malloc(sizeof(struct TERM));
cur = cur->Next;
}
}
return;
}
然后输出函数(PrintPolyn()):
这其中主要的问题是0多项式,也就是表示为<0,0>时的特判;由于我在处理中,为方便后续的结点输出,是系数为零即删除。这就需要讨论只有头结点的多项式仍有一个输出<0,0>.这里用了flag来记录是否有项输出。
void PrintPolyn(Polynomial P)
{
ptr cur = P->Next;
int flag = 0;
while (cur != NULL) {
cout << '<' << cur->Coefficient << ',' << cur->Exponent << '>';
if (cur->Next != NULL) {
cout << ',';
}
cur = cur->Next;
flag = 1;
}
if (!flag) {
cout << '<' << '0' << ',' << '0' << '>';
}
cout << endl;
return;
}
题目主要部分是多项式相加。考虑两种方式:
(1)一种是将其中一个加到另一个上,然后输出被加的这个;
(2)将结果生成为一个新的多项式。
第二种方式的遍历顺序和易错点比较少,也不需考虑一些阴间的情况,首先选择第二种。
然而,我首次采用的方式就是第一种,debug时还以为实现是错误的,而且代码也长得相当难看,最后结构比较混乱,还有goto语句。(看得出伤痕累累、受尽折磨…)这种方法实际上需要讨论指数大小的情况,类似于模拟一个人计算的过程,要先模拟对齐(which也是最折磨的)。我是将A作为被加的。大体思路是:
i、首先检测B是否为空,不然不用加了;
ii、检测A为空,这样的话需要把B复制到A,输出A;
iii、在循环中开始相加:如果A的指数小,那么需要在A中增加新的结点并赋值该B结点的值,反之一直寻找A指数更大的结点;
iv、相加时系数为0要删除,但是,删除后需要注意就只有B需要后移一位来进行下一轮;
v、在iii中需要注意的点是可能会遇到还未达到指数相等就结束的情况,这其中只有在A的系数小于B的系数的时候还需要做收尾工作(如果B结束就不加到A上了,没影响):在结束的A的尾部还需要将B的剩余部分复制。
在代码实现时,我将ii中和v中的B到A的复制操作合并了,所以出现了一个goto语句。
void AddPolyn(Polynomial Pa, Polynomial Pb)
{
ptr ptra = Pa, ptrb = Pb;
if (ptrb->Next == NULL)
return;
if (ptra->Next == NULL)
goto CopyPbToPa;
while (1) {
if (ptrb->Next->Exponent < ptra->Next->Exponent) {
while (ptrb->Next != NULL && ptrb->Next->Exponent < ptra->Next->Exponent) {
ptr cur = (ptr)malloc(sizeof(struct TERM));
cur->Next = ptra->Next;
ptra->Next = cur;
ptra = cur;
cur->Exponent = ptrb->Next->Exponent;
cur->Coefficient = ptrb->Next->Coefficient;
ptrb = ptrb->Next;
}
if (ptrb->Next == NULL) {
break;
}
continue;
}
else if (ptrb->Next->Exponent > ptra->Next->Exponent) {
while (ptra->Next != NULL && ptra->Next->Exponent < ptrb->Next->Exponent)
ptra = ptra->Next;
if (ptra->Next == NULL) {
break;
}
continue;
}
ptra->Next->Coefficient += ptrb->Next->Coefficient;
int flag = 0;
if (ptra->Next != NULL && ptra->Next->Coefficient == 0) {
ptr tmp = ptra->Next;
ptra->Next = ptra->Next->Next;
free(tmp);
flag = 1;
}
if (flag) {
ptrb = ptrb->Next;
}
else {
ptra = ptra->Next;
ptrb = ptrb->Next;
}
if (ptra->Next == NULL || NULL == ptrb->Next)
break;
}
CopyPbToPa:
while (ptrb->Next != NULL) {
ptr cur = (ptr)malloc(sizeof(struct TERM));
cur->Next = NULL;
ptra->Next = cur;
ptra = cur;
cur->Exponent = ptrb->Next->Exponent;
cur->Coefficient = ptrb->Next->Coefficient;
ptrb->Next = ptrb->Next->Next;
}
return;
}
贴源代码
还是应当给出相对好理解和使用的生成新的多项式的一种,这其中就是两列多项式同时移动,相同才相加,不相同就不加选指数小的;同时也有关于尾部结束的处理问题,但简单,也就是把没加完的加到新多项式(newpoly)
#include <iostream>
using namespace std;
typedef struct TERM* ptr;
struct TERM {
int Coefficient;
int Exponent;
ptr Next;
};
typedef ptr Polynomial;
void CreatePolyn(Polynomial P, int m);
Polynomial AddPolyn(Polynomial Pa, Polynomial Pb);
void PrintPolyn(Polynomial P);
int main() {
int status = 0;
Polynomial Pa = (ptr)malloc(sizeof(struct TERM)), Pb = (ptr)malloc(sizeof(struct TERM)), Pc = (ptr)malloc(sizeof(struct TERM));
cin >> status;
if (status) {
int m;
cin >> m;
CreatePolyn(Pa, m);
cin >> m;
CreatePolyn(Pb, m);
cin >> m;
CreatePolyn(Pc, m);
PrintPolyn(Pa);
PrintPolyn(Pb);
PrintPolyn(Pc);
Polynomial ab = AddPolyn(Pa, Pb);
PrintPolyn(ab);
Polynomial abc = AddPolyn(ab, Pc);
PrintPolyn(abc);
}
return 0;
}
void CreatePolyn(Polynomial P, int m)
{
ptr cur = P->Next = (ptr)malloc(sizeof(struct TERM));
for (int n = 0; n < m; n++)
{
int coef, comp;
cin >> coef >> comp;
cur->Coefficient = coef;
cur->Exponent = comp;
if (n == m - 1)
cur->Next = NULL;
else
{
cur->Next = (ptr)malloc(sizeof(struct TERM));
cur = cur->Next;
}
}
return;
}
Polynomial AddPolyn(Polynomial Pa, Polynomial Pb) {
ptr pa = Pa->Next, pb = Pb->Next, newpoly = (ptr)malloc(sizeof(struct TERM)), pre = newpoly, cur = NULL;
while (pa != NULL && pb != NULL) {
cur = (ptr)malloc(sizeof(struct TERM));
//新和结点
if (pa->Exponent == pb->Exponent) {
if (0 == pa->Coefficient + pb->Coefficient) {
pa = pa->Next;
pb = pb->Next;
pre->Next = NULL;
free(cur);
continue;
}
cur->Coefficient = pa->Coefficient + pb->Coefficient;
cur->Exponent = pa->Exponent;
pa = pa->Next;
pb = pb->Next;
}//可加时
else {
ptr tmp = pa->Exponent < pb->Exponent ? pa : pb;
cur->Coefficient = tmp->Coefficient;
cur->Exponent = tmp->Exponent;
if (tmp == pa) pa = pa->Next;
else pb = pb->Next;
}
//连接链表
pre->Next = cur;
cur->Next = NULL;
pre = cur;
}
while (NULL != pa) {
cur = (ptr)malloc(sizeof(struct TERM));
cur->Coefficient = pa->Coefficient;
cur->Exponent = pa->Exponent;
pa = pa->Next;
pre->Next = cur;
cur->Next = NULL;
pre = cur;
}
while (NULL != pb) {
cur = (ptr)malloc(sizeof(struct TERM));
cur->Coefficient = pb->Coefficient;
cur->Exponent = pb->Exponent;
pb = pb->Next;
pre->Next = cur;
cur->Next = NULL;
pre = cur;
}
return newpoly;
}
void PrintPolyn(Polynomial P)
{
ptr cur = P->Next;
int flag = 0;
while (cur != NULL) {
cout << '<' << cur->Coefficient << ',' << cur->Exponent << '>';
if (cur->Next != NULL) {
cout << ',';
}
cur = cur->Next;
flag = 1;
}
if (!flag) {
cout << '<' << '0' << ',' << '0' << '>';
}
cout << endl;
return;
}
——2022.10.10