设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0
。
输入样例:
4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1
输出样例:
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1 5 20 -4 4 -5 2 9 1 -2 0
#include<iostream> using namespace std; struct node { int coef; int exp; struct node *next; }; void attach(int c, int e, node **rear) { node *p = new node; p->coef = c; p->exp = e; p->next = NULL; (*rear)->next = p; *rear = p; } node *read() { int a, c, e; node *rear; node *t; cin >> a; node *blank = new node; blank->next = NULL; rear = blank; while (a--) { cin >> c >> e; attach(c, e, &rear); } t = blank; blank = blank->next; delete t; return blank; } int compare(int a, int b) { if (a > b) return 1; if (a < b) return 0; if (a == b) return -1; } node *add(node* p1, node *p2) { node *front, *rear, *tt; front = new node; front->next = NULL; rear = front; int sum = 0; while (p1&&p2) { switch (compare(p1->exp, p2->exp)) { case 1: attach(p1->coef, p1->exp, &rear); p1 = p1->next; break; case 0: attach(p2->coef, p2->exp, &rear); p2 = p2->next; break; case -1: sum = p1->coef + p2->coef; if (sum) attach(sum, p1->exp, &rear); p1 = p1->next; p2 = p2->next; break; } } for (; p1 != 0; p1 = p1->next) attach(p1->coef, p1->exp, &rear); for (; p2 != 0; p2 = p2->next) attach(p2->coef, p2->exp, &rear); tt = front; front = front->next; delete tt; return front; } void print(node *p) { if (!p) { cout << "0 0"; cout << endl; return; } int flag = 0; while (p) { if (!flag) flag = 1; else cout << " "; cout << p->coef << " " << p->exp; p = p->next; } cout << endl; } node *mult(node* p1, node *p2) { node *front, *rear, *tt, *t1, *t2; front = new node; front->next = NULL; rear = front; int c, e; if (!p1 || !p2) return NULL; t1 = p1; t2 = p2; while (t2) { c = t1->coef*t2->coef; e = t1->exp + t2->exp; attach(c, e, &rear); t2 = t2->next; } t1 = t1->next; while (t1) { t2 = p2; rear = front; while (t2) { c = t1->coef*t2->coef; e = t1->exp + t2->exp; while ((rear->next) && (rear->next->exp > e)) rear = rear->next; if ((rear->next) && (rear->next->exp == e)) { if ((rear->next->coef + c) != 0) rear->next->coef += c; else { tt = rear->next; rear->next = tt->next; delete tt; } } else { tt = new node; tt->coef = c; tt->exp = e; tt->next = rear->next; rear->next = tt; rear = rear->next; } t2 = t2->next; } t1 = t1->next; } tt = front; front = front->next; delete tt; return front; } int main() { node *p1, *p2, *pp, *ps; p1 = read(); p2 = read(); pp = add(p1, p2); ps = mult(p2, p1); print(ps); print(pp); return 0; }
以上代码我敲了好久,刚开始看到题目时我是崩溃的,看了mooc后还是不懂如何实现要求的操作。大概断断续续学了两个星期吧,还是静不下心来学,其实主要是因为难以理解其中的代码。照着ppt把代码敲下来,遇到不理解的便停下思考为什么是这样,这句代码是什么意思。磕磕绊绊学了好久,上网查阅,翻书,最后那种弄明白了其中的道理的滋味实在是舒服。做一遍这道题,对建立空节点,删除增加节点有了更深的认识,而这些对于之前的我来说是极为抽象的。通过这道题我收获了许多,以下是我从0分到20分的思考过程,附上对其中一些代码的解释,有兴趣的朋友可以看看。
本题有四个测试点,完成第一第二个可获得16分,剩下的是细节问题。
以下是0分代码,基本框架已经确定了,当时没写乘积的函数,因为和的函数都没弄懂。问题出现在使用attach函数时形参rear的传递,我用了指针rear作为形参传递,运行后总是显示出一个空格以及最后一个项的系数和指数。这个代码有多个错误,附上我当时的思考,希望帮助大家理解其中部分代码的作用。
#include<iostream> using namespace std; struct node { int coef; int exp; struct node *next; }; void attach(int c, int e, node *rear)//对形参rear的类型的定义是错误所在 { node *p = new node; p->coef = c; p->exp = e; p->next = NULL; rear->next = p; rear = p;//注意这一句的作用 } node *read()//定义为node read()不可以,而改成这个定义方式就没有错误,为什么?因为我们的返回值是指针类型。 { int a, c, e; node *rear;//建立指向节点尾部的指针 node *t; cin >> a; node *blank = new node;//建立空节点 blank->next = NULL; rear = blank;//尾部指针指向空节点 while (a--) { cin >> c >> e; attach(c, e, rear); } t = blank;//以下操作为删除空节点 blank = blank->next;//空节点指针指向第一的节点,blank->next存放的是第一个节点的地址,本操作使blank成为指向第一个节点的指针 delete t; return blank; } int compare(int a, int b) { if (a > b) return 1; if (a < b) return 0; if (a == b) return -1; } node *add(node* p1, node *p2) { node *front, *rear, *tt; front = new node; rear = front; int sum = 0; while (p1&&p2) { switch (compare(p1->exp, p2->exp)) { case 1: attach(p1->coef, p1->exp, rear); p1 = p1->next; break; case 0: attach(p2->coef, p2->exp, rear); p2 = p2->next; case -1: sum = p1->coef + p2->coef; if (sum)attach(sum, p1->exp, rear); p1 = p1->next; p2 = p2->next; break; } } for (; p1 != 0; p1 = p1->next) attach(p1->coef, p1->exp, rear); for (; p2 != 0; p2 = p2->next) attach(p2->coef, p2->exp, rear); tt = front; front = front->next; delete tt; return front; } void print(node *p) { if (!p) { cout << "0" << " " << 0 << endl; } int flag = 0; while (p) { if (!flag) flag = 1; else cout << " " << p->coef << " " << p->exp; p = p->next; } cout << endl; } int main() { node *p1, *p2, *pp; p1 = read(); p2 = read(); pp = add(p1, p2); print(pp); return 0; system("pause"); }
如果试运行以上代码,结果只显示一个空格以及最后一个项的系数和指数,我觉得是指针类型的参数在被调函数内的修改依然无法返回到主调函数中,特别是我们的attach没有返回值,rear的每次修改都无法被记录,无法达到我们的目的。其实这个点mooc上有强调,我当时没能理解。后来查阅资料,了解到一个叫做指向指针的指针,能实现我们的目的。我们要求rear在被调函数中出来后,主调函数中的rear也同时被修改。我们就需要传递指针rear的地址,用指针的地址作为形参。其实只要是传递地址,就能实现这个目的。这应该是基本知识点了。
以下依然是0分代码。大问题出现在乘积函数mult里面。
#include<iostream> using namespace std; struct node { int coef; int exp; struct node *next; }; void attach(int c, int e, node **rear) { node *p = new node; p->coef = c; p->exp = e; p->next = NULL; (*rear)->next = p; *rear = p; } node *read()/ { int a, c, e; node *rear; node *t; cin >> a; node *blank = new node; blank->next = NULL; rear = blank; while (a--) { cin >> c >> e; attach(c, e, &rear); } t = blank; blank = blank->next; delete t; return blank; } int compare(int a, int b) { if (a > b) return 1; if (a < b) return 0; if (a == b) return -1; } node *add(node* p1, node *p2) { node *front, *rear, *tt; front = new node; rear = front; int sum = 0; while (p1&&p2) { switch (compare(p1->exp, p2->exp)) { case 1: attach(p1->coef, p1->exp, &rear); p1 = p1->next; break; case 0: attach(p2->coef, p2->exp, &rear); p2 = p2->next; break; case -1: sum = p1->coef + p2->coef; if (sum) attach(sum, p1->exp, &rear); p1 = p1->next; p2 = p2->next; break; } } for (; p1 != 0; p1 = p1->next) attach(p1->coef, p1->exp, &rear); for (; p2 != 0; p2 = p2->next) attach(p2->coef, p2->exp, &rear); tt = front; front = front->next; delete tt; return front; } void print(node *p) { if (!p) { cout << "0" << " " <<" 0" << endl; } int flag = 0; while (p) { if (!flag) flag = 1; else cout << " "; cout << p->coef << " " << p->exp; p = p->next; } cout << endl; } node *mult(node* p1, node *p2) { node *front, *rear, *tt; front = new node; front->next = NULL; rear = front; int c, e; if (!p1 || !p2) return NULL; while (p2) { c = p1->coef*p2->coef; e = p1->exp +p2->exp; attach(c, e, &rear); p2 = p2->next; } p1 = p1->next; while (p1) { rear = front; while (p2)//注意这个循环,我们结束这次循环之后,需要重新从p2的头部重新开始,而我们修改了p2的值,也没有是p2重新指向头部的操作,这是为什么用t2保存p2的原因。 { c = p1->coef*p2->coef; e = p1->exp + p2->exp; while ((rear->next)&&(rear->next->exp > e)) rear = rear->next; if ((rear->next)&&(rear->next->exp == e)) { if ((rear->next->coef+c)!=0) rear->next->coef += c; else { tt = rear->next; rear->next = tt->next; delete tt; } } else { tt = new node; tt->coef = c; tt->exp = e; tt->next = rear->next; rear->next = tt; rear = rear->next; } p2 = p2->next; } p1 = p1->next; } tt = front; front = front->next; delete tt; return front; } int main() { node *p1, *p2, *pp,*ps; p1 = read(); p2 = read(); pp = add(p1, p2); ps = mult(p1, p2); print(ps); print(pp); return 0; }
我们对比满分代码,我们在mult中不是像上面这样直接对传递过来的p1,p2进行修改,而是将p1,p2分别保存在t1,t2中,相关操作对t1,t2进行。当时我在ppt中看到了,觉得多此一举,为什么不直接对p1,p2进行操作啊?答案如代码中的注释所示。
以下是18分代码。问题出现在和函数中,没办法通过第三个测试点。找到这个错误挺难的,不知道他的测试点是什么意思。还是要感谢csdn,有满分代码和前辈的解析,我从csdn看到一张测试表,找到了我的错误。
样例输入与输出:
序号 | 输入 | 输出 |
1 | 4 3 4 -5 2 6 1 -2 0 3 5 20 -7 4 3 1 |
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1 5 20 -4 4 -5 2 9 1 -2 0 |
2 | 2 1 2 1 0 2 1 2 -1 0 |
1 4 -1 0 2 2 |
3 | 2 -1000 1000 1000 0 2 1000 1000 -1000 0 |
-1000000 2000 2000000 1000 -1000000 0 0 0 |
4 | 0 1 999 1000 |
0 0 999 1000 |
#include<iostream> using namespace std; struct node { int coef; int exp; struct node *next; }; void attach(int c, int e, node **rear) { node *p = new node; p->coef = c; p->exp = e; p->next = NULL; (*rear)->next = p; *rear = p;//注意这一句的作用 } node *read()//定义为node read()不可以,而改成这个定义方式就没有错误,为什么? { int a, c, e; node *rear;//建立指向节点尾部的指针 node *t; cin >> a; node *blank = new node;//建立空节点 blank->next = NULL; rear = blank;//尾部指针指向空节点 while (a--) { cin >> c >> e; attach(c, e, &rear); } t = blank;//以下操作为删除空节点 blank = blank->next;//空节点指针指向第一的节点,blank->next存放的是第一个节点的地址,本操作使blank成为指向第一个节点的指针 delete t; return blank; } int compare(int a, int b) { if (a > b) return 1; if (a < b) return 0; if (a == b) return -1; } node *add(node* p1, node *p2) { node *front, *rear, *tt; front = new node; rear = front; int sum = 0; while (p1&&p2) { switch (compare(p1->exp, p2->exp)) { case 1: attach(p1->coef, p1->exp, &rear); p1 = p1->next; break; case 0: attach(p2->coef, p2->exp, &rear); p2 = p2->next; break; case -1: sum = p1->coef + p2->coef; if (sum) attach(sum, p1->exp, &rear); p1 = p1->next; p2 = p2->next; break; } } for (; p1 != 0; p1 = p1->next) attach(p1->coef, p1->exp, &rear); for (; p2 != 0; p2 = p2->next) attach(p2->coef, p2->exp, &rear); tt = front; front = front->next; delete tt; return front; } void print(node *p) { if (!p) { cout << "0 0";//第四个测试点在这里!!格式要注意。 cout << endl; return; } int flag = 0; while (p) { if (!flag) flag = 1; else cout << " "; cout << p->coef << " " << p->exp; p = p->next; } cout << endl; } node *mult(node* p1, node *p2) { node *front, *rear, *tt, *t1, *t2; front = new node; front->next = NULL; rear = front; int c, e; if (!p1 || !p2) return NULL; t1 = p1; t2 = p2; while (t2) { c = t1->coef*t2->coef; e = t1->exp + t2->exp; attach(c, e, &rear); t2 = t2->next; } t1 = t1->next; while (t1) { t2 = p2; rear = front; while (t2) { c = t1->coef*t2->coef; e = t1->exp + t2->exp; while ((rear->next) && (rear->next->exp > e)) rear = rear->next; if ((rear->next) && (rear->next->exp == e)) { if ((rear->next->coef + c) != 0) rear->next->coef += c; else { tt = rear->next; rear->next = tt->next; delete tt; } } else { tt = new node; tt->coef = c; tt->exp = e; tt->next = rear->next; rear->next = tt; rear = rear->next; } t2 = t2->next; } t1 = t1->next; } tt = front; front = front->next; delete tt; return front; } int main() { node *p1, *p2, *pp, *ps; p1 = read(); p2 = read(); pp = add(p1, p2); ps = mult(p2, p1); print(ps); print(pp); return 0; }
我又试着输入诸如
1 -2 1
1 2 1
等,使和函数结果应为0 0的数据,但以上代码无法正常输出并且出现错误。 使用以上数据,相同指数的系数和为0,没建立节点,后面直接让front指向front->next,我以为机器会自动认为指向空,因为这种情况下front->next没有指向任何节点。后来发现它并不能自动指向空,那我们要在刚开始定义时就要令front->next指向空,这一句很有必要,定义时若没有用NULL初始化,front->next后来被赋值了还好,一旦没有被赋值,像以上所示的数据,就会出现错误,在add函数建立空节点front时加上
front->next=NULL;
就能满分了,如满分代码。
总之,寻找错误的过程是很烦的,但最终错误被修正还是很开心的。