问题重述
一元稀疏多项式简单计算器的基本功能是:
(1)输入并建立多项式;
(2)输出多项式,输出形式为整数序列:n,c1,e1,c2,e2,…,cn,en,
其中n是多项式的项数,ci,ei分别是第i项的系数和指数,序列按指数降序排列;
(3)多项式a和b相加,建立多项式a+b;
(4)多项式a和b相减,建立多项式a-b;
(5)计算多项式在x处的值;即给定x值,计算多项式值。
拓展:多项式乘法;多项式系数的合并和排序(无论是指数大的在前面还是指数小的在前面,都可以,或者指数相同的项输入了多次,都可以进行处理,先进行多项式系数的合并和排序,形成一个指数由小到大排列多项式)
分析过程
一:输入多项式的系数和指数,初始化多项式。(其中多项式的结构如下:
typedef struct Node {
float coef; //系数
int exp; //指数
struct Node* next;
}Node, * Ploy;
typedef Ploy* ptrPloy;))//采用二重指针便于直接修改链表的值。
二:对多项式的按指数进行排序,然后将指数一样的节点进行合并。因此就实现了对序列按指数由小到大依次排序。
三:对多项式的x进行赋值求和并输出结果,就可以直接从头节点开始,遍历一遍多项式链,每到一个节点,就令coef=x(所赋予的值),然后计算coef^exp,将所有节点的值累加起来就是最终所要求的值。
四:多项式的加法与减法原理一样:现只分析加法。由于创建好的两个相加的多项式已经按指数从低到高已经排好序,对两个多项式进行加法的过程就好比对两个多项式的指数进行归并排序,在排序过程中对系数对应的系数进行加法运算,而且这里所说的归并排序只不过所用的归并不用递归,只用一趟就可以得到最终的结果,但系数相加后可能为0,就需要删除这个节点。
五:多项式的乘法(拓展):运用双层循环,将多项式1中所有的节点都与多项式2中所有的节点进行乘法运算(系数*系数,指数*指数),然后用这些节点重新构建一个多项式,最后对多项式进行排序和合并操作就可以得到最终结果,刚开始再创建多项式时会浪费n*m(n,m分别为多项式1和2的节点数),但是经过排序和合并操作就会将多余节点的空间释放掉)。
程序评价
1.多项式加法和减法的核心函数
- void Add_Ploy(ptrPloy pa, ptrPloy pb, ptrPloy pc); //进行多项式的加法
- void Sub_Ploy(ptrPloy pa, ptrPloy pb, ptrPloy pc); //进行多项式的减法
设pa长度为m,pb的长度为n
最好时间复杂度为O(Max(m,n)),最坏时间复杂度为O(m+n);
本算法不需要额外空间,首先令pc=pa,然后将pb中各个节点插入pc中合适的位置或者与pc中的节点合并。
2.在对多项式序列进行排序时,本函数采用了冒泡排序,由于数据结构为单链表,无法采用高级排序算法,希尔排序,堆排序等(这些算法用到了数组的随机存取的特点),当然这里的排序也可以使用简单选择排序或者直接插入排序,但在时间复杂度上并没有数量级的变化,但是采用简单选择排序可以减少节点交换次数。
3.设计了清晰的交互式界面,便于操作;
4.添加了外部导入文件的传输方式,并将结果写入到txt文件中,便于对后续数据的处理。
5.依据加法和减法的思想,进行拓展,增加了多项式相乘的算法。该算法的时间复杂度为O(m*n),空间复杂度为O(m*n),如果多项式的某些节点的指数值相同,就会进行合并操作并释放掉多余的空间。
6.多项式打印函数考虑情况复杂,还用多层判断语句实现对多项式的精准打印。还有在合并多项式时,也进行了精准判断,如当多项式为y=0。
源代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
//采用带链表进行多项式的加法、减法和乘法
//延伸:倘若输入的指数是无序的,而且可能是重复的,则牵扯到排序与合并。
//现尝试编写void Sort_and_Merge_Ploy(ptrPloy Head)函数
//多项式乘法void Mult_Ploy()
//多项式求和函数:对多项式赋值后进行求和void Sum_Ploy()
//多项式分解函数?
typedef struct Node {
float coef; //系数
int exp; //指数
struct Node* next;
}Node, * Ploy;
typedef Ploy* ptrPloy;
void Init_Ploy(ptrPloy Head); //初始化操作
void Add_Ploy(ptrPloy pa, ptrPloy pb, ptrPloy pc); //进行多项式的加法
void Sub_Ploy(ptrPloy pa, ptrPloy pb, ptrPloy pc); //进行多项式的减法
void Mult_Ploy(ptrPloy pa, ptrPloy pb, ptrPloy pc); //进行多项式的乘法
void Sum_Ploy(ptrPloy Head, float x,FILE* fp); //对多项式x进行赋值,然后求和
void Import_Ploy(ptrPloy Head); //输入多项式
void Sort_and_Merge_Ploy(ptrPloy Head); //对多项式内部进行排序和合并,其中排序采用快速||冒泡排序
//对单链表冒泡排序
void Bubble_Ploy(Ploy head);
//合并同类项
void Merge(Ploy head);
void Print_Ploy(ptrPloy Head,FILE* fp); //打印多项式
void Create_Ploy(ptrPloy Head,FILE* fp); //对初始化,输入,打印操作进行封装,将主函数模块化,向面向对象方法靠近
void Create_Ploy_txt(ptrPloy Head, FILE* fp); //以文本文件形式传输数据
void Final_Add_Ans(ptrPloy pa, ptrPloy pb, ptrPloy pc,FILE* fp); //输出最终相加后的结果
void Final_Sub_Ans(ptrPloy pa, ptrPloy pb, ptrPloy pc,FILE* fp); //输出最终相减后的结果
void Final_Mult_Ans(ptrPloy pa, ptrPloy pb, ptrPloy pc,FILE* fp); //输出最终相乘后的结果
void Command_Ploy(void); //命令提醒
int main()
{
ptrPloy ploy,ploy1, ploy2,ploy3;
FILE* fp;
int flag = 1;
int tag;
int way;
if ((fp = fopen("result.txt", "wb+")) == NULL) {
perror("the file fail to write");
system("pause");
exit(1);
}
while (flag) {
int choice;
float x=0;
Command_Ploy();
scanf_s("%d", &choice);
switch (choice) {
case 1:
printf("请选择数据传输方式:1.外部导入 2.手动输入\nchoice:");
scanf_s("%d", &way);
while (way < 1 || way>2) {
printf("请选择正确的传输方式:1.外部导入 2.手动输入\nchoice:");
scanf_s("%d", &way);
}
way==1?Create_Ploy_txt(&ploy,fp):Create_Ploy(&ploy,fp);
tag = 0;
break;
case 2:
printf("请输入x=");
scanf_s("%f", &x);
tag == 0 ? Sum_Ploy(&ploy, x,fp) : Sum_Ploy(&ploy3, x,fp);
break;
case 3:
fprintf(fp, "多项式加法:\n");
Create_Ploy(&ploy1,fp);
Create_Ploy(&ploy2,fp);
Final_Add_Ans(&ploy1, &ploy2, &ploy3,fp);
tag = 1;
break;
case 4:
fprintf(fp, "多项式减法:\n");
Create_Ploy(&ploy1,fp);
Create_Ploy(&ploy2,fp);
Final_Sub_Ans(&ploy1, &ploy2, &ploy3,fp);
tag = 1;
break;
case 5:
fprintf(fp, "多项式乘法:\n");
Create_Ploy(&ploy1,fp);
Create_Ploy(&ploy2,fp);
Init_Ploy(&ploy);
Final_Mult_Ans(&ploy1, &ploy2, &ploy3,fp);
tag = 1;
break;
case 6:
flag = 0;
break;
default:
break;
}
}
fclose(fp);
return 0;
}
void Init_Ploy(ptrPloy Head)
{
Ploy temp;
if (*Head == NULL);
{
temp = (Ploy)malloc(sizeof(Node));
if (*Head == NULL)
{
printf("初始化失败!\n");
return;
}
*Head = temp;
(*Head)->next = NULL;
}
printf("初始化成功!\n");
return;
}
void Add_Ploy(ptrPloy pa, ptrPloy pb, ptrPloy pc)
{
*pc = *pa;
Ploy at = (*pa)->next;
Ploy bt = (*pb)->next;
Ploy ct = (*pc);
Ploy tag;
float temp;
while (at && bt) {
if (at->exp < bt->exp) {
ct = at;
at = at->next;
}
else if (at->exp == bt->exp) {
temp = at->coef + bt->coef;
if (temp != 0) {
at->coef = temp;
ct = at;
}
else {
ct->next = at->next;
free(at);
}
at = ct->next;
bt = bt->next;
}
else {
tag = bt->next;
bt->next = at;
ct->next = bt;
ct = ct->next; // ct往后移
bt = tag;
}
}
if (bt != NULL) {
Ploy temp = (Ploy)malloc(sizeof(Node));
if (temp) {
temp = bt;
ct->next = temp;
}
//ct->next = bt;
}
//free(pb);
}
void Sub_Ploy(ptrPloy pa, ptrPloy pb, ptrPloy pc)
{
*pc = *pa;
Ploy at = (*pa)->next;
Ploy bt = (*pb)->next;
Ploy ct = (*pc);
Ploy tag;
float temp;
while (at && bt) {
if (at->exp < bt->exp) {
ct = at;
at = at->next;
}
else if (at->exp == bt->exp) {
temp = at->coef - bt->coef;
if (temp != 0) {
at->coef = temp;
ct = at;
}
else {
ct->next = at->next;
free(at);
}
at = ct->next;
bt = bt->next;
}
else {
tag = bt->next;
bt->next = at;
ct->next = bt;
bt->coef = -bt->coef;
ct = ct->next; // ct往后移
bt = tag;
}
}
if (bt != NULL) {
Ploy temp = (Ploy)malloc(sizeof(Node));
if (temp) {
bt->coef = -bt->coef;
temp = bt;
ct->next = temp;
}
//ct->next = bt;
}
//free(pb);
}
void Mult_Ploy(ptrPloy pa, ptrPloy pb, ptrPloy pc)
{
Ploy at = (*pa)->next;
Ploy bt = (*pb)->next;
//初始化pc
Ploy p;
if (*pc == NULL);
{
p = (Ploy)malloc(sizeof(Node));
if (*pc == NULL)
{
printf("初始化失败!\n");
return;
}
*pc = p;
(*pc)->next = NULL;
}
Ploy ct = *pc;
for (at; at!=NULL; at = at->next) {
for (bt=(*pb)->next; bt!=NULL; bt = bt->next) {
Ploy temp = (Ploy)malloc(sizeof(Node));
temp->coef = at->coef * bt->coef;
temp->exp = at->exp + bt->exp;
ct->next = temp;
ct = ct->next;
}
}
ct->next = NULL;
Sort_and_Merge_Ploy(pc);
}
void Sum_Ploy(ptrPloy Head, float x,FILE* fp)
{
float sum = 0;
Ploy p= (*Head)->next;
while (p) {
sum+= p->coef * pow(x, p->exp);
p = p->next;
}
printf("当x=%.2f时,多项式的总和为%.2f\n", x, sum);
fprintf(fp, "当x=%.2f时,多项式的总和为%.2f\n", x, sum);
}
void Import_Ploy(ptrPloy Head)
{
//printf("请依次输入多项式的系数和对应的指数(当输出回车时,代表输入结束)eg:1 2 3 4 回车(代表x^2+3x^4)\n");
int exp;
float coef;
char ch = 0;//用来停止输入
Ploy q = *Head;
Ploy p = (*Head)->next;
while (ch != '\n') {
scanf_s("%f %d", &coef, &exp);
p = (Ploy)malloc(sizeof(Node));
if (p) {
p->coef = coef;
p->exp = exp;
p->next = q->next;
q->next = p;
}
q = p;
p = p->next;
ch = getchar();
}
}
void Sort_and_Merge_Ploy(ptrPloy Head)
{
Ploy head = (*Head)->next;
Bubble_Ploy(head);
//再Merge
Merge(head);
}
void Bubble_Ploy(Ploy head)
{
Ploy p, q;
int exp;
float coef;
if (head == NULL || head->next == NULL) {
return;
}
for (p = head; p != NULL; p = p->next) {
for (q = p->next; q != NULL; q = q->next) {
if (p->exp > q->exp) {
exp = p->exp;
coef = p->coef;
p->exp = q->exp;
p->coef = q->coef;
q->exp = exp;
q->coef = coef;
}//if
}//for
}//for
}
void Merge(Ploy head)
{
Ploy q = (head);
Ploy p = q->next;
while (p) {
while (p != NULL&&(p->exp == q->exp)) {
q->coef += p->coef;
p = p->next;
}
if (q->coef == 0) {
if (p == NULL) {
q->coef = 0;
q->exp = 0;
}
else {
q->coef = p->coef;
q->exp = p->exp;
if (p->next == NULL) p = NULL;
else p = p->next;
}
q->next = p;
}
else {
if (p == NULL) {
q->next = p;
}
else {
q->next = p;
q = q->next;
p = p->next;
}//else
}//else
}//while
}
void Print_Ploy(ptrPloy Head,FILE* fp)
{
int flag = 0;
Ploy p = (*Head)->next;
printf("y=");
fprintf(fp, "y=");
while (p) {
if (p->coef != 0) {
if ((p)->exp == 0) {
printf("%.0f", (p)->coef);
fprintf(fp, "%.0f", (p)->coef);
flag = 1;
}
else if ((p)->coef > 0) {
if ((p)->coef == 1) {
if ((p)->exp == 1) {
flag == 0 ? printf("x") : printf("+x");
flag==0?fprintf(fp, "x") :fprintf(fp, "+x");
flag = 1;
}
else {
flag == 0 ? printf("x^%d", (p)->exp) : printf("+x^%d", (p)->exp);
flag == 0 ? fprintf(fp,"x^%d", (p)->exp) : fprintf(fp,"+x^%d", (p)->exp);
flag = 1;
}
}
else {
if (p->exp == 1)
{
printf("%.0fx", p->coef);
fprintf(fp, "%.0fx", p->coef);
}
else {
flag == 0 ? printf("%.0fx^%d", (p)->coef, (p)->exp) : printf("+%.0fx^%d", (p)->coef, (p)->exp);
flag == 0 ? fprintf(fp,"%.0fx^%d", (p)->coef, (p)->exp) : fprintf(fp,"+%.0fx^%d", (p)->coef, (p)->exp);
}
flag = 1;
}
}
else {
if ((p)->coef == -1) {
if ((p)->exp == 1) {
printf("-x");
fprintf(fp, "-x");
flag = 1;
}
else {
printf("-x^%d", (p)->exp);
fprintf(fp,"-x^%d", (p)->exp);
flag = 1;
}
}
else {
if (p->exp == 1) {
printf("%.0fx", p->coef);
fprintf(fp,"%.0fx", p->coef);
}
else {
printf("%.0fx^%d", (p)->coef, (p)->exp);
fprintf(fp, "%.0fx^%d", (p)->coef, (p)->exp);
}
flag = 1;
}//else
}//else
}
p = p->next;
}
//如果没有输出其他格式,说明多项式为0
if (flag == 0) {
printf("0");
fprintf(fp, "0");
}
printf("\n");
fprintf(fp, "\n");
return;
}
void Create_Ploy(ptrPloy Head,FILE* fp)
{
printf("ploy:");
Init_Ploy(Head);
printf("请依次输入ploy多项式的系数和对应的指数(可以不用按递增顺序输入,当输出回车时, 代表输入结束)\neg:1 2 3 4 回车(代表x ^ 2 + 3x ^ 4)\ninput:");
Import_Ploy(Head);
Sort_and_Merge_Ploy(Head);
printf("你输入的ploy多项式为:\noutput:");
Print_Ploy(Head,fp);
}
void Create_Ploy_txt(ptrPloy Head, FILE* fp)
{
printf("ploy:");
Init_Ploy(Head);
FILE* fp1;
int exp;
float coef;
char ch = 0;//用来停止输入
Ploy q = *Head;
Ploy p = (*Head)->next;
if ((fp1 = fopen("ploy.txt", "r")) == NULL) {
perror("the file ploy.txt fail to read");
system("pause");
exit(1);
}
while (!feof(fp1) && !ferror(fp1)) {
fscanf(fp1, "%f%d", &coef,&exp);
p = (Ploy)malloc(sizeof(Node));
if (p) {
p->coef = coef;
p->exp = exp;
p->next = q->next;
q->next = p;
}
q = p;
p = p->next;
}
Sort_and_Merge_Ploy(Head);
printf("你输入的ploy多项式为:\noutput:");
Print_Ploy(Head, fp);
}
void Final_Add_Ans(ptrPloy pa, ptrPloy pb, ptrPloy pc,FILE* fp)
{
printf("即将进行相加:\n");
system("pause");
Add_Ploy(pa, pb, pc);
printf("两多项式相加后的结果如下:\n");
fprintf(fp,"两多项式相加后的结果如下:\n");
Print_Ploy(pc,fp);
}
void Final_Sub_Ans(ptrPloy pa, ptrPloy pb, ptrPloy pc,FILE* fp)
{
printf("即将进行相减:\n");
system("pause");
Sub_Ploy(pa, pb, pc);
printf("两多项式相减后的结果如下:\n");
fprintf(fp, "两多项式相减后的结果如下:\n");
Print_Ploy(pc,fp);
}
void Final_Mult_Ans(ptrPloy pa, ptrPloy pb, ptrPloy pc,FILE* fp)
{
printf("即将进行相乘:\n");
system("pause");
Mult_Ploy(pa, pb, pc);
printf("两多项式相乘后的结果如下:\n");
fprintf(fp, "两多项式相乘后的结果如下\n");
Print_Ploy(pc,fp);
}
void Command_Ploy(void)
{
printf("*********************************请输入多项式的操作命令********************************\n");
printf("操作命令提醒:\n1.创建一个多项式 2.多项式赋值求和 3.多项式相加 4.多项式相减 5.多项式相乘 6.退出\n");
printf("***************************************************************************************\n");
printf("Cmd:");
}
测试
测试1: