题目网址:https://pintia.cn/problem-sets/15/problems/710
题目描述:设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分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
题目分析:这道题的关键不是算法,而是用来存储系数和指数的数据结构的选择。通常我们的第一反应是用数组,数组的第i个元素存储 x^i 这一项的系数,但是一旦遇到多项式乘法后,数组将会变成一个稀疏矩阵,加上项数的不确定性,可能会导致存储空间的不足,因此数组是很坏的一个选择。那么既具有灵活存储又能动态分配内存空间的ADT非链表莫属了。
算法解析:由于题目要求按照指数降序输出,因此为了方便链表元素前后搜索或置换,我采用了双向链表。
- 多项式加法:按照归并排序中归并的方法,定义一个头结点名为sum的链表存储加法结果,每次取两个多项式头部的元素进行比较,小的先进入sum链表,若相等则系数相加后进入链表。进入链表的元素所在的节点指针指向下一个直至NULL
- 多项式乘法:定义一个头结点名为mul的链表存储乘法结果。乘法的难点在于不能向加法那样顺序增添节点,这时每个节点的last和next指针就有用了。采用最笨拙的暴力搜索,使两个多项式一项一项分别相乘,将所乘得到的结果与mul尾结点比较,若尾结点指数大,则添加至新尾结点,若尾结点指数小,则用一个新的循环向前搜索,直至找到正确的位置,插入,若与尾结点指数相同,则系数相加即可。同时要注意各链表指针的变化。
- 输出:考虑到存在零多项式(项数为0或结果系数为0的情况),我统一在输出函数进行处理
AC代码:我的算法可能有些笨拙,如果有更好的算法,还请大佬们留言告知,谢谢
#include<stdio.h>
#include<stdlib.h>
struct Node{
struct Node* last;
int cof;
int exp;
struct Node* next;
};
int m,n;
struct Node* Creat(int k);
struct Node* Print(struct Node* head);
struct Node* Sum(struct Node* head1, struct Node *head2);
struct Node* Mul(struct Node* head1, struct Node *head2);
int main()
{
struct Node* head1, *head2;
struct Node* sum, *mul;
scanf("%d",&m);
if (m!=0)
{
head1 = Creat(m);
}
else
{
head1 = (struct Node*)malloc(sizeof(struct Node));
head1->cof = head1->exp = 0;
head1->last = head1->next = NULL;
}
scanf("%d",&n);
if (n!=0)
{
head2 = Creat(n);
}
else
{
head2 = (struct Node*)malloc(sizeof(struct Node));
head2->cof = head2->exp = 0;
head2->last = head2->next = NULL;
}
sum = Sum(head1, head2);
mul = Mul(head1, head2);
Print(mul);
printf("\n");
Print(sum);
}
struct Node* Creat(int k)
{
struct Node* head, *tail, *p;
int i;
for (i=0; i<k; i++)
{
p = (struct Node*)malloc(sizeof(struct Node));
scanf("%d %d",&p->cof, &p->exp);
if (i==0)
{
head = tail = p;
tail->next = NULL;
head->last = NULL;
}
else
{
tail->next = p;
p->last = tail;
tail = p;
p->next = NULL;
}
}
return head;
}
struct Node* Print(struct Node* head) //同时处理零多项式的情况
{
int count = 0;
if (head==NULL)
{
printf("0 0");
return NULL;
}
while (head!=NULL)
{
if (head->cof==0)
{
head = head->next;
continue;
}
if (count==0)
{
printf("%d %d",head->cof,head->exp);
count = 1;
}
else
{
printf(" %d %d",head->cof, head->exp);
}
head = head->next;
}
if (count==0) printf("0 0");
}
struct Node* Sum(struct Node* head1, struct Node *head2)
{
struct Node*sum = NULL, *head = NULL, *tail = NULL;
while (head1!=NULL && head2!=NULL)
{
sum = (struct Node*)malloc (sizeof(struct Node));
if (head==NULL)
{
head = tail = sum;
head->last = NULL;
tail->next = NULL;
}
else
{
tail->next = sum;
sum->last = tail;
tail = sum;
tail->next = NULL;
}
if (head1->exp==head2->exp)
{
sum->cof = head1->cof + head2->cof;
sum->exp = head1->exp;
head1 = head1->next;
head2 = head2->next;
}
else if(head1->exp > head2->exp)
{
sum->cof = head1->cof;
sum->exp = head1->exp;
head1 = head1->next;
}
else
{
sum->cof = head2->cof;
sum->exp = head2->exp;
head2 = head2->next;
}
}
while (head1!=NULL)
{
sum = (struct Node*)malloc(sizeof(struct Node));
tail->next = sum;
sum->last = tail;
tail = sum;
tail->next = NULL;
sum->cof = head1->cof;
sum->exp = head1->exp;
head1 = head1->next;
}
while (head2!=NULL)
{
sum = (struct Node*)malloc(sizeof(struct Node));
tail->next = sum;
sum->last = tail;
tail = sum;
tail->next = NULL;
sum->cof = head2->cof;
sum->exp = head2->exp;
head2 = head2->next;
}
return head;
}
struct Node* Mul(struct Node* head1, struct Node *head2)
{
struct Node* mul = NULL, *head = NULL, *tail = NULL, *find = NULL, *insert = NULL;
struct Node* newhead = NULL;
if (m==0||n==0)
{
return NULL;
}
while (head1!=NULL)
{
newhead = head2;//防止丢失原链表头结点
while (newhead!=NULL)
{
mul = (struct Node*)malloc(sizeof(struct Node));
if (head==NULL)
{
head = tail = mul;
head->last = NULL;
tail->next = NULL;
}
mul->cof = head1->cof * newhead->cof;
mul->exp = head1->exp + newhead->exp;
if (mul->exp < tail->exp)//如果所得结果小于mul的尾结点指数,则增添为新的尾结点
{
tail->next = mul;
mul->last = tail;
tail = mul;
tail->next = NULL;
}
else
{
find = tail;
while (find->last!=NULL && mul->exp > find->exp)//想前搜索至正确位置
find = find->last;
if (mul->exp < find->exp)
{
insert = (struct Node*)malloc(sizeof(struct Node));
insert->cof = mul->cof;
insert->exp = mul->exp;
//inserting
find->next->last = insert;
insert->last = find;
insert->next = find->next;
find->next = insert;
mul = NULL;
}
else //mul->exp==find->exp
{
if (find->last!=NULL)
find->cof += mul->cof;
mul = NULL;
}
}
newhead = newhead->next;
}
head1 = head1->next;
}
return head;
}