一、实验要求
二、代码实现
以下C语言代码实现了多项式的加减法、乘法、求导和顶点求值的功能。
(水平有限,代码存在不规范之处)
编程环境:Window11 + Visual Studio
#define _CRT_SECURE_NO_WARNINGS 1
# include <stdio.h>
# include <stdlib.h>
# include <malloc.h>
# include <math.h>
# define Error -1
# define OK 1//一个节点记录多项式中的一项
typedef struct Polynode
{float coef; //系数int exp; //指数struct Polynode* next;
}Polynode, * Polypointer;void Menu(Polypointer a, Polypointer b);
Polypointer InitialNode(void);
int CreatePolynomial(Polypointer a, char* filename);
void PrintPoly(Polypointer a);
Polypointer CopyPoly(Polypointer a);
Polynode* AttachNode(float ceof, int e, Polynode* pre);
void AddPoly(Polypointer a, Polypointer b, Polypointer c);
void MinusPoly(Polypointer a, Polypointer b, Polypointer c);
void MultiPoly(Polypointer a, Polypointer b, Polypointer c);
void MultiPoly_2(Polypointer a, Polypointer b, Polypointer c);
Polypointer DiffPoly(Polypointer a, int k);
double GetValue(Polypointer a, double x);
int Write(Polypointer a, char* outfile);
void ClearList(Polypointer a);
//int ReadFromOnefile(Polypointer a,Polypointer b,char*file);int main(void)
{Polypointer a = InitialNode();Polypointer b = InitialNode();Polypointer c = InitialNode();Polypointer d = InitialNode();Polypointer e = InitialNode();Polypointer f = InitialNode();char* file1 = "Polynomial01.txt";char* file2 = "Polynomial02.txt";char* outfile = "OutPolynomial.txt";CreatePolynomial(a, file1);CreatePolynomial(b, file2);int order;do{Menu(a, b);printf("\n请输入指令:\t");scanf("%d", &order);switch (order){case 0:printf("退出\n");break;case 1:{printf("\nf1+f2=");AddPoly(a, b, c);PrintPoly(c);Write(c, outfile);break;}case 2:{printf("\nf1-f2=");MinusPoly(a, b, d);PrintPoly(d);Write(d, outfile);break;}case 3:{printf("\nf1*f2=");MultiPoly_2(a, b, e);PrintPoly(e);Write(e, outfile);break;}case 4:{int k;do{printf("请输入求导的阶数\n");scanf("%d", &k);} while (k < 0);f = DiffPoly(a, k);printf("d(%d)f1 = ", k);if (f->next) PrintPoly(f);else printf("0\n");Write(f, outfile);break;}case 5:{printf("请输入x来求值f1(x)\n");double x;scanf("%lf", &x);double value = GetValue(a, x);printf("\nf1(%.2lf) = %.3lf", x, value);break;}default:printf("指令不存在\n");break;}} while (order);return 0;
}void Menu(Polypointer a, Polypointer b)
{printf("\n-----------------------------------\n");printf("链表实现多项式的运算\n");printf("f1 = ");PrintPoly(a);printf("f2 = ");PrintPoly(b);printf("1:加法\n");printf("2:减法 f1-f2\n");printf("3:乘法\n");printf("4:对f1求k阶导\n");printf("5:对f1求值\n");printf("0:退出\n");printf("-----------------------------------\n");return;
}
//创建链表的头节点,初始化链表
Polypointer InitialNode(void)
{Polynode* p = (Polynode*)malloc(sizeof(Polynode));if (p == NULL) return NULL;p->coef = 0;p->exp = 0;p->next = NULL;return p;
}//从文件中读取多项式信息,并创建降序排列的多项式
int CreatePolynomial(Polypointer a, char* filename)
{FILE* fp;fp = fopen(filename, "r");if (fp == NULL){printf("file open failure\n");return Error;}Polynode* q = NULL;while (feof(fp) == 0) //feof非0表示未到文件末尾{q = (Polynode*)malloc(sizeof(Polynode)); //申请新的节点,把读到的数据放到q指向的节点中if (q == NULL) return Error;q->next = NULL;fscanf(fp, "%f %d", &q->coef, &q->exp);if (q->coef == 0) //若读到的系数为0,释放该节点{free(q);continue;}Polynode* pre = a;Polynode* cur = a->next;while (cur && q->exp < cur->exp) //找比q中指数小的节点{pre = cur;cur = pre->next;}if (cur && cur->exp == q->exp) //若链表中已经存在指数相等节点,系数相加即可{cur->coef = cur->coef + q->coef;free(q);if (cur->coef == 0){pre->next = cur->next;free(cur);}continue;}pre->next = q; //把q节点接入到链表中q->next = cur;}fclose(fp);return OK;
}//将多项式打印到屏幕上
void PrintPoly(Polypointer a)
{Polynode* p = a->next;while (p){if (p->coef > 0){printf("+");}printf("%.2fx^%d", p->coef, p->exp);p = p->next;}printf("\n");return;
}//为申请的节点赋值,并且链接到pre后面
Polynode* AttachNode(float c, int e, Polynode* pre)
{Polynode* temp = (Polynode*)malloc(sizeof(Polynode));if (temp == NULL) return NULL;temp->next = NULL;temp->coef = c;temp->exp = e;pre->next = temp;return temp;
}//两个一元多项式相加
void AddPoly(Polypointer a, Polypointer b, Polypointer c)
{Polynode* p1 = a; //p1指向第一个多项式Polynode* p2 = b; //p2指向第二个多项式Polynode* cur = c;while (p1 && p2){if (p1->exp > p2->exp){cur = AttachNode(p1->coef, p1->exp, cur);p1 = p1->next;}else if (p2->exp > p1->exp){cur = AttachNode(p2->coef, p2->exp, cur);p2 = p2->next;}else if (p1->exp == p2->exp){float sum = p1->coef + p2->coef;if (fabs(sum) <= 1e-6) //如果系数和为0{p1 = p1->next;p2 = p2->next;}else{cur = AttachNode(sum, p1->exp, cur);p1 = p1->next;p2 = p2->next;}}}while (p1){cur = AttachNode(p1->coef, p1->exp, cur);p1 = p1->next;}while (p2){cur = AttachNode(p2->coef, p2->exp, cur);p2 = p2->next;}
}//多项式减法 多项式a减多项式b
void MinusPoly(Polypointer a, Polypointer b, Polypointer c)
{Polypointer copyb;copyb = CopyPoly(b);Polynode* p = copyb->next;while (p){p->coef = p->coef * (-1);p = p->next;}AddPoly(a, copyb, c);return;
}//多项式乘法 乘法通过多项式的累加实现
void MultiPoly(Polypointer a, Polypointer b, Polypointer c)
{Polynode* p1 = a->next;Polynode* p2 = b->next;Polynode* p3 = c;//每次用a中的一项乘b中的每一项生成一个临时多项式//将临时多项式与现有的c相加Polypointer headtemp = InitialNode(); //每次生成的多项式的头节点Polynode* ptemp = headtemp; //ptemp是指向临时多项式当前操作节点的指针while (p1){ClearList(headtemp);ptemp = headtemp;while (p2){Polynode* temp = (Polynode*)malloc(sizeof(Polynode));if (temp == NULL) return;temp->next = NULL;temp->coef = p1->coef * p2->coef;temp->exp = p1->exp + p2->exp;AttachNode(temp->coef, temp->exp, ptemp);ptemp = ptemp->next;p2 = p2->next;}AddPoly(c, headtemp, c); //把生成的多项式累加p1 = p1->next; //p1指向下一项p2 = b->next; //p2指向b的起始位置}
}//对乘法进行优化,减少频繁的节点分配
//因为每次生成的多项式是相同长度的,所以临时多项式的节点可以反复利用
void MultiPoly_2(Polypointer a, Polypointer b, Polypointer c)
{Polynode* p1 = a->next;Polynode* p2 = b->next;Polynode* p3 = c;Polypointer headtemp = InitialNode(); //临时多项式的头节点Polynode* ptemp = headtemp; //ptemp是指向临时多项式当前操作节点的指针//先对a中的第一项,生成临时链表if (p1){while (p2){Polynode* temp = (Polynode*)malloc(sizeof(Polynode));if (temp == NULL) return;temp->next = NULL;temp->coef = p1->coef * p2->coef;temp->exp = p1->exp + p2->exp;AttachNode(temp->coef, temp->exp, ptemp);ptemp = ptemp->next;p2 = p2->next;}AddPoly(c, headtemp, c); //把生成的多项式累加p1 = p1->next; //p1指向下一项p2 = b->next; //p2指向b的第一项}//对临时链表反复利用while (p1){ptemp = headtemp->next;while (p2){ptemp->coef = p1->coef * p2->coef;ptemp->exp = p1->exp + p2->exp;ptemp = ptemp->next;p2 = p2->next;}AddPoly(c, headtemp, c);p1 = p1->next;p2 = b->next;}
}//拷贝给定的多项式
Polypointer CopyPoly(Polypointer a)
{Polypointer b;b = InitialNode();Polynode* p1 = a->next;Polynode* p2 = b;while (p1){Polynode* t = (Polynode*)malloc(sizeof(Polynode));if (t == NULL) return NULL;t->next = NULL;t->coef = p1->coef;t->exp = p1->exp;p2->next = t;p1 = p1->next;p2 = p2->next;}return b;
}//对多项式求k阶导
Polypointer DiffPoly(Polypointer a, int k)
{Polypointer c = CopyPoly(a); //将多项式a拷贝一份Polynode* p1 = c; //p1记录着p2的前一个节点Polynode* p2 = c->next;for (int i = 0; i < k; ++i){p1 = c;p2 = c->next;while (p2){p2->coef = p2->coef * p2->exp;p2->exp--;if (p2->exp < 0) //对常数求导得到的节点需要去掉{p2->coef = 0;p1->next = p2->next;free(p2);p2 = p1->next;}else{p1 = p1->next;p2 = p2->next;}}}return c;
}//求多项式的值
double GetValue(Polypointer a, double x)
{double sum = 0;Polynode* p = a->next;while (p){sum += p->coef * pow(x, p->exp);p = p->next;}return sum;
}//把多项式写入指定文件
int Write(Polypointer a, char* outfile)
{FILE* fp = fopen(outfile, "a");if (fp == NULL){printf("file open failure\n");return Error;}Polynode* p = a->next;while (p){if (p->coef > 0){fprintf(fp, "+");}fprintf(fp, "%.2fx^%d", p->coef, p->exp);p = p->next;}fprintf(fp, "\n");fclose(fp);return OK;
}//清空链表,保存头节点
void ClearList(Polypointer a)
{Polynode* p1 = a->next;Polynode* p2;while (p1){p2 = p1->next;free(p1);p1 = p2;}a->next = NULL;
}