设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分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
通过题意的理解我们可以发现本质是对多项式各项的系数指数进行一系列的处理。
一般我们处理这种线性结构都是可以利用2种方法:
解决方法:
一,结构体数组
#include<stdio.h>
#define MAXN 2001
#define MAXK 10
#define ERROR -1
typedef struct {
int coef; // coefficient
int expn; // exponent
} polynomial;
polynomial poly[MAXN * 2];
int result[MAXN * 2] = {0};
void add(polynomial poly[], int n) {
for (int i = 0; i < n; i++) {
result[poly[i].expn] += poly[i].coef;
}
}
void multiply(polynomial poly1[], int n1, polynomial poly2[], int n2) {
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
result[poly1[i].expn + poly2[j].expn] += poly1[i].coef * poly2[j].coef;
}
}
}
void printPoly(int result[], int n) {
int flag = 0;
for (int i = n; i >= 0; i--) {
if (result[i] != 0) {
if (flag != 0) printf(" ");
printf("%d %d", result[i], i);
flag = 1;
}
}
if (flag == 0) printf("0 0\n");
else printf("\n");
}
int main() {
int k1, k2;
scanf("%d", &k1);
for (int i = 0; i < k1; i++) {
scanf("%d %d", &poly[i].coef, &poly[i].expn);
}
scanf("%d", &k2);
for (int i = k1; i < k1 + k2; i++) {
scanf("%d %d", &poly[i].coef, &poly[i].expn);
}
multiply(poly, k1, poly + k1, k2);
printPoly(result, MAXN * 2);
memset(result, 0, sizeof(result));
add(poly, k1 + k2);
printPoly(result, MAXN * 2);
return 0;
}
可以先看主函数main里面的,由于绝对值均为不超过1000的整数,所以我定义了一个2002大小的结构体数组,接下来分别输入2个所要处理多项式的系数指数,下面就是2个主要的函数
这2个函数我们需要知道的是数组下标是指多项式每一项的指数,对应的数组存储数据是系数
一,乘法处理
void multiply(polynomial poly1[], int n1, polynomial poly2[], int n2) {
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
result[poly1[i].expn + poly2[j].expn] += poly1[i].coef * poly2[j].coef;
}
}
}
乘法操作中我们是利用第一个多项式的每一项去乘第二个多项式的每一项最后累加。这里利用了2层for循环
外层循环为拿出第一个多项式每一项,内层也是,所以里面操作为 result[poly1[i].expn + poly2[j].expn] += poly1[i].coef * poly2[j].coef;
每相乘的2项的指数相加(即poly1[i].expn + poly2[j].expn )对应相应下标的数组数据为系数相乘poly1[i].coef * poly2[j].coef;
二,加法处理
void add(polynomial poly[], int n) {
for (int i = 0; i < n; i++) {
result[poly[i].expn] += poly[i].coef;
}
}
加法运算我们利用相同指数下标所存储的数据相加 即是相同指数的项的系数相加,
三,打印输出
void printPoly(int result[], int n) {
int flag = 0;
for (int i = n; i >= 0; i--) {
if (result[i] != 0) {
if (flag != 0) printf(" ");
printf("%d %d", result[i], i);
flag = 1;
}
}
if (flag == 0) printf("0 0\n");
else printf("\n");
}
由于输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数,所以我们for循环输出是从n递减循环的。
很好理解初始化flag为0,为了控制空格打印以及特殊情况的处理。
1.在一直没有找到数组内数据(即系数)不为0时flag恒为0,不会打印空格。知道出现第一组数据后flag改变为1,之后循环输出。由于flag变成1后恒为1,所以会自动打印每组数据后打印空格。
2.如果flag恒为0,说明为零多项式,应输出0 0.
二,链表实现
#include<stdio.h>
typedef struct PolyNode *Polynomial;
struct PolyNode {
int coef; // coefficient
int expon; // exponent
Polynomial link;
};
Polynomial ReadPoly() {
int N, c, e;
Polynomial P, Rear, t;
scanf("%d", &N);
P = (Polynomial)malloc(sizeof(struct PolyNode));
P->link = NULL;
Rear = P;
while (N--) {
scanf("%d %d", &c, &e);
Attach(c, e, &Rear);
}
t = P; P = P->link; free(t);
return P;
}
void Attach(int c, int e, Polynomial *pRear) {
Polynomial P;
P = (Polynomial)malloc(sizeof(struct PolyNode));
P->coef = c;
P->expon = e;
P->link = NULL;
(*pRear)->link = P;
*pRear = P;
}
Polynomial Add(Polynomial P1, Polynomial P2) {
Polynomial front, rear, temp;
int sum;
rear = (Polynomial)malloc(sizeof(struct PolyNode));
front = rear;
while (P1 && P2) {
if (P1->expon > P2->expon) {
Attach(P1->coef, P1->expon, &rear);
P1 = P1->link;
} else if (P1->expon < P2->expon) {
Attach(P2->coef, P2->expon, &rear);
P2 = P2->link;
} else {
sum = P1->coef + P2->coef;
if (sum) Attach(sum, P1->expon, &rear);
P1 = P1->link;
P2 = P2->link;
}
}
for (; P1; P1 = P1->link) Attach(P1->coef, P1->expon, &rear);
for (; P2; P2 = P2->link) Attach(P2->coef, P2->expon, &rear);
temp = front;
front = front->link;
free(temp);
return front;
}
Polynomial Mult(Polynomial P1, Polynomial P2) {
Polynomial P, Rear, t1, t2, t;
int c, e;
if (!P1 || !P2) return NULL;
t1 = P1; t2 = P2;
P = (Polynomial)malloc(sizeof(struct PolyNode)); P->link = NULL;
Rear = P;
while (t2) {
Attach(t1->coef*t2->coef, t1->expon+t2->expon, &Rear);
t2 = t2->link;
}
t1 = t1->link;
while (t1) {
t2 = P2; Rear = P;
while (t2) {
e = t1->expon + t2->expon;
c = t1->coef * t2->coef;
while (Rear->link && Rear->link->expon > e)
Rear = Rear->link;
if (Rear->link && Rear->link->expon == e) {
if (Rear->link->coef + c)
Rear->link->coef += c;
else {
t = Rear->link;
Rear->link = t->link;
free(t);
}
} else {
t = (Polynomial)malloc(sizeof(struct PolyNode));
t->coef = c; t->expon = e;
t->link = Rear->link;
Rear->link = t;
Rear = Rear->link;
}
t2 = t2->link;
}
t1 = t1->link;
}
t2 = P; P = P->link; free(t2);
return P;
}
void PrintPoly(Polynomial P) {
int flag = 0;
if (!P) {
printf("0 0\n");
return;
}
while (P) {
if (!flag)
flag = 1;
else
printf(" ");
printf("%d %d", P->coef, P->expon);
P = P->link;
}
printf("\n");
}
int main() {
Polynomial P1, P2, PP, PS;
P1 = ReadPoly();
P2 = ReadPoly();
PP = Mult(P1, P2);
PrintPoly(PP);
PS = Add(P1, P2);
PrintPoly(PS);
return 0;
}
我们还是先看主函数
int main() {
Polynomial P1, P2, PP, PS;
P1 = ReadPoly();
P2 = ReadPoly();
PP = Mult(P1, P2);
PrintPoly(PP);
PS = Add(P1, P2);
PrintPoly(PS);
return 0;
}
初始化4个链表,2个输入,2个为处理后的返回值,最后直接打印。
设计5个函数
ReadPoly() ;void PrintPoly ;Mult(Polynomial P1, Polynomial P2) ;Add(Polynomial P1, Polynomial P2) ;
Attach(int c, int e, Polynomial *pRear)
首先输入函数
Polynomial ReadPoly() {
int N, c, e;
Polynomial P, Rear, t;
scanf("%d", &N);
P = (Polynomial)malloc(sizeof(struct PolyNode));
P->link = NULL;
Rear = P;
while (N--) {
scanf("%d %d", &c, &e);
Attach(c, e, &Rear);
}
t = P; P = P->link; free(t);
return P;
}
-
int N, c, e;
: 这里声明了三个整型变量N
、c
和e
,分别用于存储输入的项数、系数和指数。 -
Polynomial P, Rear, t;
: 这里声明了三个变量,其中P
是指向多项式头节点的指针,Rear
是指向多项式尾节点的指针,t
是一个临时节点指针。 -
scanf("%d", &N);
: 从标准输入中读取一个整数,该整数表示多项式的项数。 -
P = (Polynomial)malloc(sizeof(struct PolyNode));
: 使用malloc
函数为多项式的头节点分配内存空间,并将头节点指针赋值给P
。 -
P->link = NULL;
: 将头节点的link
域(指向下一个节点的指针)置为空,表示目前还没有实际的多项式项。 -
Rear = P;
: 将Rear
指针指向头节点,此时头节点也是尾节点,因为目前还没有多项式项。 -
while (N--) { ... }
: 这是一个循环,循环的次数为输入的项数N
。在循环内部,将会读取每个多项式项的系数和指数,并将其添加到多项式中。 -
scanf("%d %d", &c, &e);
: 从标准输入中读取两个整数,分别表示当前项的系数和指数。 -
Attach(c, e, &Rear);
: 调用Attach
函数,将当前项的系数和指数以及尾节点的指针传递给它。Attach
函数的作用是将当前项添加到多项式中。 -
t = P; P = P->link; free(t);
: 将头节点P
暂存到临时指针t
中,然后将P
指向多项式的第一个实际节点(跳过头节点),最后释放之前的头节点t
。 -
return P;
: 返回多项式的头节点指针,即返回一个指向多项式的指针。
总的来说,ReadPoly()
函数的作用是从标准输入读取多项式的项数、系数和指数,然后构建一个链表表示的多项式,并返回多项式的头节点指针。这个函数使用了链表数据结构来动态地构建多项式,将每个项作为链表的一个节点,最终形成一个表示多项式的链表。
其中用到了attach函数
void Attach(int c, int e, Polynomial *pRear) {
Polynomial P;
P = (Polynomial)malloc(sizeof(struct PolyNode));
P->coef = c;
P->expon = e;
P->link = NULL;
(*pRear)->link = P;
*pRear = P;
}
负责将当前项添加到多项式中。之后便是最重要的乘法和加法。
一,加法运算
Polynomial Add(Polynomial P1, Polynomial P2) {
Polynomial front, rear, temp;
int sum;
rear = (Polynomial)malloc(sizeof(struct PolyNode));
front = rear;
while (P1 && P2) {
if (P1->expon > P2->expon) {
Attach(P1->coef, P1->expon, &rear);
P1 = P1->link;
} else if (P1->expon < P2->expon) {
Attach(P2->coef, P2->expon, &rear);
P2 = P2->link;
} else {
sum = P1->coef + P2->coef;
if (sum) Attach(sum, P1->expon, &rear);
P1 = P1->link;
P2 = P2->link;
}
}
for (; P1; P1 = P1->link) Attach(P1->coef, P1->expon, &rear);
for (; P2; P2 = P2->link) Attach(P2->coef, P2->expon, &rear);
temp = front;
front = front->link;
free(temp);
return front;
}
主要为判断,
当P1,P2都非空时:当P1>P2指数时,插入P1,反之插入P2, 插入后链表往后移动一个单位,相等时,P1,P2系数相加,插入和系数 与对应指数,P1,P2都往后移。
当有一个为空时,判断谁不为空,把剩下的插入到链表最后,最后利用temp释放最初申请的空间。
temp = front; front = front->link; free(temp);
: 在循环结束后,将头节点 front
暂存到 temp
中,然后将 front
指向链表的第一个实际节点,最后释放之前的头节点 temp
,确保不再使用它。
二,乘法运算
Polynomial Mult(Polynomial P1, Polynomial P2) {
Polynomial P, Rear, t1, t2, t;
int c, e;
if (!P1 || !P2) return NULL;
t1 = P1; t2 = P2;
P = (Polynomial)malloc(sizeof(struct PolyNode)); P->link = NULL;
Rear = P;
while (t2) {
Attach(t1->coef*t2->coef, t1->expon+t2->expon, &Rear);
t2 = t2->link;
}
t1 = t1->link;
while (t1) {
t2 = P2; Rear = P;
while (t2) {
e = t1->expon + t2->expon;
c = t1->coef * t2->coef;
while (Rear->link && Rear->link->expon > e)
Rear = Rear->link;
if (Rear->link && Rear->link->expon == e) {
if (Rear->link->coef + c)
Rear->link->coef += c;
else {
t = Rear->link;
Rear->link = t->link;
free(t);
}
} else {
t = (Polynomial)malloc(sizeof(struct PolyNode));
t->coef = c; t->expon = e;
t->link = Rear->link;
Rear->link = t;
Rear = Rear->link;
}
t2 = t2->link;
}
t1 = t1->link;
}
t2 = P; P = P->link; free(t2);
return P;
}
乘法运算,我们要做的就是把乘法运算转化为加法运算
我们首先做判断有没有零多项式,之后我们通过第二个多项式的第一项去乘以第一个多项式的第一项,从而得到了一个多项式地基,为后面的加法运算做准备。
并且做了一个处理 t1 = t1->link;,去掉第一项。
之后我们看到所做的while循环
while (t1) {
t2 = P2; Rear = P;
while (t2) {
t2 = t2->link;
}
t1 = t1->link;
}
可以看出来外层循环先是对t1第一项,第二项等等,内层循环则是从t2第一项逐项处理。
即为每一项与每一项的相乘得到后 加到我们刚开始得到的多项式地基上。
while (Rear->link && Rear->link->expon > e)
Rear = Rear->link;
if (Rear->link && Rear->link->expon == e) {
if (Rear->link->coef + c)
Rear->link->coef += c;
else {
t = Rear->link;
Rear->link = t->link;
free(t);
}
} else {
t = (Polynomial)malloc(sizeof(struct PolyNode));
t->coef = c; t->expon = e;
t->link = Rear->link;
Rear->link = t;
Rear = Rear->link;
}
可以发现判断每两项相乘的指数和多项式的每一项进行比较,之后分情况处理
相等直接加,不相等肯定是小于,则选择插入。最后返回得到的新链表。
三,打印输出
void PrintPoly(Polynomial P) {
int flag = 0;
if (!P) {
printf("0 0\n");
return;
}
while (P) {
if (!flag)
flag = 1;
else
printf(" ");
printf("%d %d", P->coef, P->expon);
P = P->link;
}
printf("\n");
}
和我上面讲的第一种方法里面的输出思路一样,不再多讲。
如果有什么不理解的欢迎大家在评论区问我
如果有什么不对的地方敬请斧正