一、实验要求![](https://img-blog.csdnimg.cn/9f60e81e2422432d8f3c07867fc306dd.png)
二、代码实现
以下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;
}