目录
题目描述
7-2 一元多项式的乘法与加法运算 (20 分)
设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分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
分析思路:
1.题目很复杂,考虑用一条链表表示一个多项式,链表每个节点代表一个项。
2.要谨慎关注项的合并,零多项式,合并后系数为0的等等特殊情况。
源代码:
#include<iostream>
#include<cstdio>
using namespace std;
using Pnomial = struct PNode*;
struct PNode
{
int coe = 0, expon = 0;//系数和指数
Pnomial Next;//指针域
};
int compare(int a, int b)
{
if (a == b)
return 0;
else if (a > b)
return 1;
else
return -1;
}
void attach(int C, int E, Pnomial* Rear)//C,C++的函数都是值传递,传入指针才能
//真实修改传入的量,所以这里传入的是指针的指针
{
Pnomial p = (Pnomial)malloc(sizeof(struct PNode));
//申请节点存放当前项系数和指数
p->coe = C;
p->expon = E;
p->Next = NULL;//填装新节点内容
(*Rear)->Next = p;//连接节点
*Rear = p; //把rear位置后移,rear始终保持在多项式的最后一项
}
Pnomial read()
{
int n, c, e;
scanf("%d", &n);
Pnomial front, beg, rear;
front = (Pnomial)malloc(sizeof(struct PNode));//先构造一个临时空节点
front->Next = NULL;
rear = front;
while (n--)
{
scanf("%d%d", &c, &e);
attach(c, e, &rear);
}
beg = front;//beg停留在临时节点上
front = front->Next;//把front移到真实的第一项
free(beg);
return front;//返回真实第一项多项式指针
}
Pnomial add(Pnomial t1, Pnomial t2)
{
Pnomial front, beg, rear, s1 = t1, s2 = t2;
front = (Pnomial)malloc(sizeof(struct PNode));//先构造一个临时空节点
front->Next = NULL;
rear = front;
while (s1&&s2)//两多项式都还没读到最后一项的时候
{
switch (compare(s1->expon, s2->expon))
{
case 1:
{
attach(s1->coe, s1->expon, &rear);
s1 = s1->Next;
}
break;
case 0:
{
if (s1->coe + s2->coe)//如果合并不为0
attach(s1->coe + s2->coe, s1->expon, &rear);
else//为0不放入
;
s1 = s1->Next;
s2 = s2->Next;
}
break;
case -1:
{
attach(s2->coe, s2->expon, &rear);
s2 = s2->Next;
}
break;
}
}
while (s1)//s1还有项没读完的时候
{
attach(s1->coe, s1->expon, &rear);
s1 = s1->Next;
}
while (s2)//s2还有项没读完的时候
{
attach(s2->coe, s2->expon, &rear);
s2 = s2->Next;
}
beg = front;
front = front->Next;
free(beg);
return front;
}
Pnomial multy(Pnomial t1, Pnomial t2)
{
if (!t1 || !t2)
return NULL;
Pnomial front, beg, rear, s1 = t1, s2 = t2;
front = (Pnomial)malloc(sizeof(struct PNode));//先构造一个临时空节点
front->Next = NULL;
rear = front;
while (s2)//先初始化结果多项式,用s1的第一项乘以s2的每一项
{
attach(s1->coe*s2->coe, s1->expon + s2->expon, &rear);
s2 = s2->Next;
}
s1 = s1->Next;
while (s1)
{
s2 = t2; rear = front;//把rear移回临时空节点,从头往后遍历寻找插入位置
while (s2)
{
int c = s1->coe*s2->coe;
int e = s1->expon + s2->expon;
while (rear->Next&&rear->Next->expon > e)//寻找可以插入结果多项式的项
rear = rear->Next;
if (rear->Next&&rear->Next->expon == e)
{
rear->Next->coe += c;//如果指数相同的要合并同类项
if (!(rear->Next->coe))//如果合并完为0,就要删除这一项
{
Pnomial m = rear->Next;
rear->Next = m->Next;
free(m);
}
}
else//指数不同就申请新节点插入
{
Pnomial j = (Pnomial)malloc(sizeof(struct PNode));
j->Next = NULL;
j->coe = c;
j->expon = e;
j->Next = rear->Next;
rear->Next = j;
}
s2 = s2->Next;
}
s1 = s1->Next;
}
beg = front;
front = front->Next;
free(beg);
return front;
}
void print(Pnomial p)
{
if (!p)
{
printf("0 0");
return;
}
int flag = 0;
while (p)
{
if(flag)
cout <<" ";
printf("%d %d", p->coe, p->expon);
p = p->Next;
if(!flag)
flag = 1;
}
}
int main()
{
Pnomial p1, p2,pp,addpp;
p1 = read();
p2 = read();
pp = multy(p1, p2);
print(pp);
cout << endl;
addpp = add(p1, p2);
print(addpp);
return 0;
}
学习心得
以前虽然也学习数据结构,但是没有用数据结构完成做过一道题目。这道题目可以算是真正意义上的第一题。这道题还是很有意义的,尤其是对于数据结构入门的小白们(比如我),可以很好地理解数据结构在题目里地实际应用,并且学会读入一个数据结构和输出一个数据结构。同时对于C语言的学习者来说能提高对指针的理解能力和掌握能力。