NO.6多项式相乘
题目要求
题目说明:
要求采用链表形式,求两个一元多项式的乘积:h3 = h1*h2。函数原型为:void multiplication( NODE * h1, NODE * h2, NODE * h3 )。
输入:
输入数据为两行,分别表示两个一元多项式。每个一元多项式以指数递增的顺序输入多项式各项的系数(整数)、指数(整数)。
例如:1+2x+x2表示为:<1,0>,<2,1>,<1,2>,
输出:
以指数递增的顺序输出乘积: <系数,指数>,<系数,指数>,<系数,指数>,
零多项式的输出格式为:<0,0>,
我们看一下输入输出样例:
| 测试输入 | 期待的输出 | 时间限制 | 内存限制 | |
|---|---|---|---|---|
| 测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 1024KB |
| 测试用例 4 | 以文本方式显示
| 以文本方式显示
| 1秒 | 1024KB |
| 测试用例 5 | 以文本方式显示
| 以文本方式显示
| 1秒 | 1024KB |
预设代码
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{ int coef, exp;
struct node *next;
} NODE;
void multiplication( NODE *, NODE * , NODE * );
void input( NODE * );
void output( NODE * );
void input( NODE * head )
{ int flag, sign, sum, x;
char c;
NODE * p = head;
while ( (c=getchar()) !='\n' )
{
if ( c == '<' )
{ sum = 0;
sign = 1;
flag = 1;
}
else if ( c =='-' )
sign = -1;
else if( c >='0'&& c <='9' )
{ sum = sum*10 + c - '0';
}
else if ( c == ',' )
{ if ( flag == 1 )
{ x = sign * sum;
sum = 0;
flag = 2;
sign = 1;
}
}
else if ( c == '>' )
{ p->next = ( NODE * ) malloc( sizeof(NODE) );
p->next->coef = x;
p->next->exp = sign * sum;
p = p->next;
p->next = NULL;
flag = 0;
}
}
}
void output( NODE * head )
{
while ( head->next != NULL )
{ head = head->next;
printf("<%d,%d>,", head->coef, head->exp );
}
printf("\n");
}
int main()
{ NODE * head1, * head2, * head3;
head1 = ( NODE * ) malloc( sizeof(NODE) );
input( head1 );
head2 = ( NODE * ) malloc( sizeof(NODE) );
input( head2 );
head3 = ( NODE * ) malloc( sizeof(NODE) );
head3->next = NULL;
multiplication( head1, head2, head3 );
output( head3 );
return 0;
}
信息梳理
我们先看一下题目的输入:
< a , b > ,
尖括号中间有两个数,然后接一个逗号,这样即使多项式的一项。
然后给出了三个函数:
void multiplication( NODE *, NODE * , NODE * );
void input( NODE * );
void output( NODE * );
其中input、output已经完成,要求我们完成相乘操作multiplication。
然后我们试着先手推一遍:
操作很常规,将两个表达式中的每一项相乘,然后再相加。此时我们发现,似乎有点小问题,也就是指数相同的项并没有合并,这显然不符合题目的要求,所以我们还需要将指数相同的项合并。
然后我们注意一下题目已经实现的两个操作,在input中发现用来接收两个表达式的链表都是有头结点的,并且是采用尾插法插入的。所以我们在实现想成操作时要注意一下!!!
代码实现
NODE *current1 = h1->next;
NODE *current2;
NODE *temp, *tail = NULL;
PS:这里说明一下,相乘顺序是先固定h1中第一项,然后遍历h2中的每一项,以此类推。
为了创建结果链表更加方便,我使用带尾结点的链表*tail,然后相乘过程中肯定是要遍历h1、h2两个链表的,所以用两层循环:
while (current1 != NULL) {
current2 = h2->next;
while (current2 != NULL) {
temp = (NODE*)malloc(sizeof(NODE));
temp->coef = current1->coef * current2->coef;
temp->exp = current1->exp + current2->exp;
temp->next = NULL;
if (h3->next == NULL) { //结果链表h3中还没有结点
h3->next = temp;
tail=temp;
} else {
tail->next = temp;
tail = temp;
}
current2 = current2->next;
}
current1 = current1->next;
}
思路还是比较简单的,先明确循环终止的条件就是两个表达式链表都遍历完了。然后就是结构体结点的两个元素coef(系数)、exp(指数)的处理逻辑:
temp = (NODE*)malloc(sizeof(NODE));
temp->coef = current1->coef * current2->coef;
temp->exp = current1->exp + current2->exp;
temp->next = NULL;
定义一个结构体预存结果,然后系数是两项系数相乘的结果,而指数是两项指数相加的结果。
然后就是将预存链表加到结果链表h3中去:
if (h3->next == NULL) {
h3->next = temp;
tail=temp;
} else {
tail->next = temp;
tail = temp;
}
然后更新current2,继续遍历。当遍历完一遍好h2后,我应该更更新current1了,这里就要注意将current2重置为指向第一项!!!
然后我们可以看一下初步的运行结果:

可以发现运算的结果是没有问题的,只不过是指数相同的项还没有合并,然后接下来我们想办法实现合并操作:
思路也比较简单,就是先固定一个结点*pre,然后用结点*current来遍历后面的结点,然后比较两者的指数。如果相等,就将p->coef=p->coef+current->coef,但是这样做完并没有真正实现,指数相同两项的合并,因为current此时还依旧在那,我们还需要将其从结果链表中删除。
假如这是当前状态 :

下一步就应该是:

那么此时可以发现,pre->exp==current->exp,那么我就要完成合并操作,如下图:

change记录的是current的上一个,所以只要将current删去再更新即可,只要想到记录好上一个current也就是change就会比较简单。
所以我们可以这样写:
NODE *pre = h3->next;
NODE *current = pre->next;
NODE *change =pre; //change用来记录已经比较过的结点(也就是上一个current)
int flag=0;
while(pre!=NULL){
current =pre->next;
while(current!=NULL){
if(pre->exp==current->exp){
pre->coef=pre->coef+current->coef;
change->next=current->next;
current=current->next;
}
else{
change=current;
current=current->next;
}
}
pre=pre->next;
change=pre;
}
然后应该就没有问题了,我们试着运行一下,你会发现,对于测试用例4,出现了一个很好气又好笑的问题:

因为它居然将系数为0的项,一本正经地保留了下来!!!
所以我们还需要处理一下结果链表h3中,系数为0的项:
NODE *cur = h3->next;
NODE *pre1 = h3;
while(cur!=NULL){
if(cur->coef==0){
pre->next=cur->next;
}
pre=cur;
cur=cur->next;
}//遍历一遍,将系数为0的项删除即可(当时心里暗爽,就要过了,爽!!!)
然后我们再提交一下:

没有问题!!!
源代码
多项式相乘
源码放在上面了(^///^)
写这道题的时候,比较有感触,就是做题真的会给人带来成就感,不管这道题是简单还是难!
与君共勉!!!

1521

被折叠的 条评论
为什么被折叠?



