02-线性结构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
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode {
int data;
int expo;
struct LNode *next;
} LNode, *Linklist;
Linklist Read (void);
Linklist Attach (Linklist L1, LNode *r);
Linklist Sum (Linklist L1, Linklist L2);
Linklist Multi (Linklist L1, Linklist L2);
void my_print (Linklist L);
int main () {
Linklist L1, L2, sum, multi;
L1 = Read();
L2 = Read();
sum = Sum (L1, L2);
multi = Multi (L1, L2);
my_print (multi);
printf ("\n");
my_print (sum);
return 0;
}
//构造带头结点链表
Linklist Read (void) {
int num, times, n; //times为次数
int i;
LNode *p, *L;
L = (LNode*) malloc (sizeof(LNode));
L->next = NULL;
LNode *tail;
tail = L;
scanf ("%d", &n);
for (i = 0; i < n; i++) {
p = (LNode*) malloc (sizeof(LNode));
scanf ("%d %d", &num, ×);
p->data = num;
p->expo = times;
p->next = NULL;
tail->next = p;
tail = p;
}
return L;
}
//计算两个多项式的和
Linklist Sum (Linklist L1, Linklist L2) {
Linklist tail = (Linklist) malloc (sizeof(LNode)); //创建链表头结点
tail->next = NULL;
Linklist L = tail;
Linklist p = L1->next;
Linklist q = L2->next;
while (p && q) {
Linklist r = (Linklist) malloc (sizeof(LNode)); //新建一个节点r,保存求和的数据
if (p->expo > q->expo) {
r->data = p->data;
r->expo = p->expo;
r->next = NULL;
tail->next = r;
tail = tail->next;
p = p->next;
} else if (p->expo < q->expo) {
r->data = q->data;
r->expo = q->expo;
r->next = NULL;
tail->next = r;
tail = tail->next;
q = q->next;
} else {
r->data = q->data + p->data;
r->expo = q->expo;
r->next = NULL;
tail->next = r;
tail = tail->next;
p = p->next;
q = q->next;
}
}
if(p) tail->next = p;
if(q) tail->next = q;
//将L中数据为0的节点清除
p = L;
q = L->next;
while (q) {
if (q->data == 0) {
LNode *t = q;
p->next = q->next;
q = q->next;
free (t);
} else {
p = p->next;
q = q->next;
}
}
return L;
}
//计算两个多项式的乘积
Linklist Multi (Linklist L1, Linklist L2) {
LNode *p, *q, *r;
p = L1->next;
q = L2->next;
Linklist L = (Linklist) malloc (sizeof(LNode));
L->next = NULL;
LNode *tail = NULL;
while (p) {//顺序移动L1与L2相乘
while (q) {//顺序移动L2,依次与L1当前元素计算
r = (LNode *) malloc (sizeof(LNode));
r->data = p->data * q->data;
r->expo = p->expo + q->expo;
r->next = NULL;
L = Attach (L, r);
q = q->next;
}
q= L2->next;
p = p->next;
}
//将L中数据为0的节点清除
p = L;
q = L->next;
while (q) {
if (q->data == 0) {
LNode *t = q;
p->next = q->next;
q = q->next;
free (t);
} else {
p = p->next;
q = q->next;
}
}
return L;
}
//将新结点添加入链表
Linklist Attach (Linklist L1, LNode *r) {
LNode *p, *q;
p = L1;
q = L1->next;
if (q == NULL) {
p->next = r;
return L1;
}
while (1) { //查找合适位置,插入后就跳出循环
if (r->expo > q->expo) { //r的指数大于q的指数时,在p、q之间插入
r->next = q;
p->next = r;
break;
} else if (r->expo == q->expo) { //如果r的指数与q的指数相同,将r的数据加到q上
q->data = q->data + r->data;
break;
} else { //如果r的指数小于q的指数,p、q依次后移
p = p->next;
q = q->next;
if (q == NULL) { //如果p已经为链表的最后一个元素,说明当前r的指数已经是链表中的最小值
p->next = r;
break;
}
}
}
return L1;
}
//函数打印
void my_print (Linklist L) {
L = L->next;
if (L == NULL) printf ("0 0"); //按照题意,当结果为0多项式时,应输出0 0
while (L) {
printf ("%d %d",L->data, L->expo);
if (L->next) printf (" ");
L = L->next;
}
return;
}
为满足输出0 0,需要知道在多项式里:
如果变数项(x) 的系数皆为0 ,就成为一种特例,叫做[常数多项式]
常数多项式里,如果连常数项也是0,就又是一种特例,叫做[零多项式]
其他的就叫做[零次多项式]
由于每次计算乘法和加法之后,均对链表数据进行处理,删除掉了所有data域为0的节点,因此在打印时只需要去判断 L->next是否为NULL即可以知道当前是否为零多项式。
PTA运行结果: