这是一道非常经典的计算题,两个多项式相乘。
但是个人觉得就是还是有一小部分的内存泄漏隐患和那个代码注释尚未解释完全。希望之后能够做的更好。
大多数的代码何钦铭老师都已经给出来了,个人只是实现了一下Add那个函数之中的业务。感觉还有很多可以写。
暂时代码如下:
#include<stdio.h>
#include<stdlib.h>
typedef struct PolyNode *Polynomial;
struct PolyNode
{
int coef; // 一元多项式的系数
int expon; // 一元多项式的指数
Polynomial link; // 指向下一个结点的指针
};
Polynomial ReadPoly(); /* 读取并生成链表 */
void PrintPoly(Polynomial P); /* 打印链表数组 */
void Attach(int c, int e, Polynomial *pRear); /* 在链表尾增加一个结点 */
Polynomial Add(Polynomial P1, Polynomial P2); /* 链表相加 */
Polynomial Mult(Polynomial P1, Polynomial P2); /* 链表相乘 */
void FreePoly(Polynomial P); /* 释放资源 */
void Attach(int c, int e, Polynomial *pRear)
{
Polynomial P;
/* 为新结点申请属于它的内存空间
* 这里还是需要判断一下是否能够申请成功
* 做好容错处理
*/
P = (Polynomial)malloc(sizeof(struct PolyNode));
if(P == NULL)
{
printf("ERROR!\n");
exit(EXIT_FAILURE); /* 不可使用return EXIT_FAILURE; 因为结构体不一致*/
}
// printf("Memory allocated\n");
P->coef = c; /* 对新结点系数赋值 */
P->expon = e; /* 对新结点指数赋值 */
P->link = NULL; /* P的下一个结点置为空 */
(*pRear)->link = P;
*pRear = P; /* 修改pRear值 */
}
Polynomial ReadPoly()
{
Polynomial P; // P为需要传出的实际链表头节点
Polynomial Rear; // Rear为指向链表尾部
Polynomial t; // t为临时指向链表尾的结点
int c = 0; // 设置每一个传进来的系数的临时存放变量为0
int e = 0; // 设置每一个传进来的指数的临时存放变量为0
int N = 0; // 设置链表长度为0,默认为空链表
if(scanf("%d", &N) == 1) // 读入具体的多项式的项数且验证是否读取正确
{ /* Do nothing */ }
else // 如果输入错误则输出读取整数异常
{
printf("Fail to read integer.\n");
}
P = (Polynomial)malloc(sizeof(struct PolyNode));/* 新建一条链表 不要默认申请成功 */
if(P == NULL) // 如果真的申请失败了需要选择退出
{
printf("ERROR!\n");
exit(EXIT_FAILURE); /* 不可使用return EXIT_FAILURE; 因为结构体不一致*/
}
P->link = NULL; /* 链表头结点置为空 */
Rear = P; /* Rear尾结点指向链表 */
while(N--) // 循环读入各个多项式的参数和系数
{
/* 读入第N个数据的系数和指数 */
/* 如果函数读取正确的话就执行下一步 */
/*
* ReadPoly 中 scanf("%d %d", &c, &e) == 1 是错误的:scanf 读取两个整数时,成功会返回 2,而非 1。该错误会导致输入校验逻辑失效,无法正确判断系数和指数是否读取成功。
* 修正来自豆包AI
*/
if(scanf("%d %d", &c, &e) == 2)
{ /* 系数和指数均需输入正确 */ }
else /* 如果输入出现问题的话需要打印报错 */
{
printf("Fail to read integer.\n");
}
Attach(c, e, &Rear); /* 将读入的数据赋值新结点添加到链表尾部 */
}
// 删除临时生成的头节点
t = P; // t指向P
P = P->link; // P指向下一个
free(t); // 释放t
return P; // 返回相加的链表P
}
Polynomial Add(Polynomial P1, Polynomial P2)
{
Polynomial P; // 准备反馈的链表P
Polynomial t; // 准备指向P的头结点的t
Polynomial t1; // 准备指向P1头节点的t1
Polynomial t2; // 准备指向P2头节点的t2
Polynomial Rear; // 最开始指向P的尾结点
// ......
t1 = P1; // t1指向P1
t2 = P2; // t2指向P2
P = (Polynomial)malloc(sizeof(struct PolyNode));
if(P == NULL)
{
printf("ERROR!\n");
exit(EXIT_FAILURE);/* 不可使用return EXIT_FAILURE; 因为结构体不一致*/
}
P->link = NULL;
Rear = P; // Rear指向P
while(t1 && t2)
{
if(t1->expon == t2->expon) // t1和t2指数相等
{
/* 这里需要判断一种情况
* 如果说就是t1的系数和t2的系数互相抵消
* 比如t1的系数为1, t2的系数为-1, 两者相加为0
* 这种需要就是抵消掉
* 其余的情况需要合并同类项
*/
if(t1->coef + t2->coef != 0)
{
Attach(t1->coef + t2->coef, t1->expon, &Rear);
}
/* 添加了结点之后,指向链表的指针分别往后移动一位 */
t1 = t1->link;
t2 = t2->link;
}
if(t1->expon > t2->expon) // 如果t1所指向的指数比t2所指向的指数大
{ // ......
Attach(t1->coef, t1->expon, &Rear); // 将t1所指添加到链表尾
t1 = t1->link; // t1移动到后一位
}
if(t1->expon < t2->expon) // 如果t1所指向的指数比t2所指向的指数小
{ // ......
Attach(t2->coef, t2->expon, &Rear); // 将t2所指添加到链表尾
t2 = t2->link; // t2移动到后一位
}
} // 循环结束说明P1或P2至少有一个链表为空
while(t1) // 若t1所指向的P1不为空
{ // ......
Attach(t1->coef, t1->expon, &Rear);// 持续添加t1所指向的结点到链表尾部
t1 = t1->link;
}
while(t2) // 若t2所指向的P2不为空
{ // ......
Attach(t2->coef, t2->expon, &Rear);// 持续添加t2所指向的结点到链表尾部
t2 = t2->link;
}
/* 删除临时生成的头节点 */
t = P; // t指向P
P = P->link; // P指向下一个
free(t); // 释放t
return P; // 返回P1相加P2之后的链表P
}
Polynomial Mult(Polynomial P1, Polynomial P2)
{
// ......
Polynomial P; /* 返回的链表P */
Polynomial Rear; /* 指向链表尾结点 */
Polynomial t; /* 用于释放头节点的变量 */
Polynomial t1; /* 指向P1链表的t1 */
Polynomial t2; /* 指向P1链表的t1 */
int c;
int e;
if(!P1 || !P2) /* P1或者P2空 */
{
return NULL; /* 返回空 */
}
t1 = P1; /* t1指向p1 */
t2 = P2; /* t2指向p2 */
// ......
P = (Polynomial)malloc(sizeof(struct PolyNode));
if(P == NULL)
{
printf("ERROR!\n");
exit(EXIT_FAILURE);/* 不可使用return EXIT_FAILURE; 因为结构体不一致*/
}
P->link = NULL;
Rear = P; /* 链表尾结点Rear指向P */
while(t2) /* 先用P1的第1项乘以P2,得到P */
{ // ......
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));
if(t == NULL)
{
printf("ERROR!\n");
exit(EXIT_FAILURE);/* 不可使用return EXIT_FAILURE; 因为结构体不一致*/
}
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"); // 则输出0 0
return;
}
while(P) // 当传入的链表不为空的时候
{
if(flag) // 如果flag != 0
{
printf(" "); // 输入一个分号
}
if(!flag) // 如果flag == 0
{
flag = 1; // 将flag置为1
}
printf("%d %d", P->coef, P->expon);
P = P->link; // P为下一项
}
printf("\n"); // 换行,表示当前多项式已经输出完了
}
void FreePoly(Polynomial P)
{
Polynomial t;
while(P)
{
t = P;
P = P->link;
free(t);
}
}
int main(int argc, char *argv[])
{
/* 1.读入多项式1
* 2.读入多项式2
* 3.乘法运算并输出
* 4.假发运算并输出
* 5.如果使用了链表,需要释放申请了的内存
*/
Polynomial P1;
Polynomial P2;
Polynomial PP;
Polynomial PS; // 不是Play Station, 更不是PhotoShop
P1 = ReadPoly();
P2 = ReadPoly();
PP = Mult(P1, P2);
PrintPoly(PP);
PS = Add(P1, P2);
PrintPoly(PS);
FreePoly(P1);
FreePoly(P2);
FreePoly(PP);
FreePoly(PS);
return 0;
}
浙公网安备 33010602011771号