一元多项式

自动生成数据无需文件导入

加法 减法 乘法 不定积分 求导 求值 多项式系数包含小数正负

运算结果和时间消耗保存在文件中

#include <stdio.h>
#include <stdlib.h>//多项式中数据按指数递增在文件中存储 
#include <math.h>
#include <time.h>//除了加法 将时间测试放在test函数里,别的直接放在原函数里
 
 //初始多项式随机生成 和 多项式运算结果保存在文件里 不用手动输入数据 解放双手 可以通过rand范围 生成任意项数和任意指数,系数有正负小数的多项式保存在文件里,进行多项式运算时再从文件里读取多项式
 //加法系数正负小数考虑到浮点数误差 采用fabs()求绝对值与 1e-6 比较判断系数是否为0 
 
// 因为多项式每一项指数是随机生成的 会重复 生成指数相同乱序的项在文件里,所以每次从文件里读取数据都进行了排序,且考虑了指数相同项的合并

//多项式求值时可以自己选择未知元x的值计算  因为考虑到用户输入数据 所以对非法输入 进行了 处理 和 提示 体现了程序的健壮性 509行 

//  会在time文件里记录加、减、乘、求值、求积分、基本操作次数和时间花费  通过改变每次生成多项式的项式可以得到得到算法关于问题规模的时间复杂度

FILE * time_file = NULL;//记录所有运算结果的文件指针
 
clock_t start, stop;/*clock_t是clock()函数返回的变量类型*/ 

double duration;/*记录时间,单位秒*/ 

int cnt  = 0;//计算每次算法基本操作次数 

typedef struct Node
{
	float ceof;
    int expon;
	struct Node *next;
}PolyNode,*Polynomial;


void CreateInformation(void){//生成任意次幂,任意项式的一元多项式并存在文件中 
	char filename1[30] = {"Polynomial1.txt"};
	char filename2[30] = {"Polynomial2.txt"};
	
	FILE *fp1 = NULL,*fp2 = NULL;
	
	int n = 0; 
	
	fp1 = fopen(filename1,"w");
	fp2 = fopen(filename2,"w");
	

	srand((unsigned) time(NULL));	/*初始化随机数发生器*/
	
	while(n < 5000) n = rand()%6000;//控制多项式长度 
	printf("第一个多项式长度为%d\n",n);
	
	for(int i = 0;i < n ;i++)
		fprintf(fp1,"%f %d\n",rand()%1000 - 300 + 1/(float)(rand()%1000),rand()%100);//rand()%50 0 -49的伪随机数 
	
	
	n = 0; 
	while(n < 5000) n = rand()%6000;//控制多项式长度 
	printf("第二个多项式长度为%d\n",n);

	for(int i = 0;i < n ;i++)
		fprintf(fp2,"%f %d\n",rand()%1000 - 300 + 1/(float)(rand()%1000),rand()%100);//rand()%50 0 -49的伪随机数 
	

	fclose(fp1);//关闭文件 
	fclose(fp2); 
	
}

void PrintInformationTofile(char *filename,Polynomial prior){//将运算得到的结果多项式打印到文件中 
	FILE * fp = NULL;
	cnt = 0;
	fp = fopen(filename,"w");
	
	while(prior){
		cnt++;
		if(prior->expon)
        	fprintf(fp,"%fx^%d  ",prior->ceof,prior->expon);
        else fprintf(fp,"%f	 ",prior->ceof);
        prior = prior->next;
        
        if(!(cnt%3))
        	fprintf(fp,"\n");
	}
	
	fclose(fp); //一定要记得关闭文件 
} 

void PrintPolynomial(Polynomial prior){//将多项式输出到屏幕上 
	
	
	while(prior){
		cnt++;
		
		if(prior->expon)
        	printf("%fx^%d ",prior->ceof,prior->expon);
        else printf("%f	",prior->ceof);
        prior = prior->next;
       
        if(!(cnt%3))
       		printf("\n"); //3项换行 
	}
	
	 
} 

Polynomial GetPolynomial(char *filename){//从文件读取多项式
    Polynomial head = NULL,prior=NULL,rear = NULL,s=NULL;//head头结点,prior前驱,rear后继
    head = (Polynomial)malloc(sizeof(PolyNode));
    head->next = NULL;
   
   FILE *fp = NULL;
   fp = fopen(filename,"r");
   if(!fp) printf("文件打开失败\n");
   
   while(!feof(fp)){//未到文件末尾时读取数据
        s = (Polynomial)malloc(sizeof(PolyNode));
        s->next = NULL;
        //printf("kkk\n"); 
        if(fscanf(fp,"%f %d",&s->ceof,&s->expon) == 2){//防止feof()特性带来的误差
        	prior = head;
        	rear = head->next;
        	while(rear && s->expon > rear->expon){//边读边排序 按指数升序排序 
        		prior = rear;
        		rear = rear->next;
			}//循环退出后s指数小于等于rear指数 
			if(rear && rear->expon == s->expon){//当指数相同时 
				rear->ceof+=s->ceof;

				if(fabs(rear->ceof) < 1e-6) //系数为0 
				{
					prior->next = rear->next;//各项无效 
					free(rear);
				}
				continue;
			} 
			prior->next = s;
			s->next = rear;
			
		}else{
			free(s);
			break;//否则文件指针将继续后移 
		}
        
    }
    
    prior = head->next;
    free(head);
    
    fclose(fp);//一定要关闭文件
	return prior;
	
}


Polynomial PolynomialAdd(Polynomial p1,Polynomial p2){//多项式加法,通过比较指数和判断系数,从p1,p2中整合出p3
    Polynomial head = NULL,prior = NULL,same = NULL;//head头指针,prior前驱指针,same指向要释放的空间
    //cnt = 0;//记录基本操作加法会调用减法 
	 
    head = (Polynomial)malloc(sizeof(PolyNode));
    head->next = NULL;//一定要赋空
    
    prior = head;
		
    while(p1 && p2)
    {
    	cnt+=6; 
        if(p1->expon < p2->expon){//p1指数小于p2
            prior->next = p1;
            p1 = p1->next;
            prior = prior->next;
        }else if(p1->expon > p2->expon){//p1指数大于p2
            prior->next = p2;
            p2 = p2->next;
            prior = prior->next;
        }else{//指数相等
            p1->ceof+=p2->ceof;
            if(fabs(p1->ceof) >= 1e-6)//防止浮点数误差 和系数为0 
            {
               
                prior->next = p1;
                prior = prior->next;

                p1 = p1->next;
                same = p2;//此时p1结点插入释放p2
    
                p2 = p2->next;
                free(same); 
            }else{
                same = p1;//一定要free掉
                p1 = p1->next;
                free(same);

                same = p2;
                p2 = p2->next;
                free(same);
            }
        }
    }
    prior->next = p1?p1:p2;
    //p1?prior->next = p1 : prior->next = p2;//连接多项式p1或p2剩余部分
    
   
    prior = head->next;
    free(head);//释放头结点
    
    return prior;
}

Polynomial PolynomialSub(Polynomial p1,Polynomial p2){//多项式减法p1-p2,通过比较指数和判断系数,从p1,p2中整合出p3
    Polynomial head = NULL,prior = NULL,same = NULL;//head头指针,prior前驱指针,same指向要释放的空间
    head = (Polynomial)malloc(sizeof(PolyNode));
    
    head->next = NULL;//一定要赋空
    prior = head;
    
    
    
    while(p1 && p2)
    {
    	cnt+=6;//基本语句较多 
        if(p1->expon < p2->expon){//p1指数小于p2
            prior->next = p1;
            p1 = p1->next;
            prior = prior->next;
        }else if(p1->expon > p2->expon){//p1指数大于p2
            prior->next = p2;
            p2->ceof = -p2->ceof; 
            p2 = p2->next;
            prior = prior->next;
        }else{//指数相等
            p1->ceof-=p2->ceof;
            if(fabs(p1->ceof) >= 1e-6)//防止浮点数误差
            {
               
                prior->next = p1;
                prior = prior->next;

                p1 = p1->next;

                same = p2;//此时p1结点插入释放p2
                p2 = p2->next;
                
            }else{//系数为0 
                same = p1;//一定要free掉
                p1 = p1->next;
                free(same);

                same = p2;
                p2 = p2->next;
                free(same);
            }
        }
    }
    p1?prior->next = p1 : prior->next = p2;//连接多项式p1或p2剩余部分
    
    if(prior->next == p2) {//判断剩余除数还是余数 
    	prior = prior->next;
	    while(prior){
	    	cnt+=2; 
	    	prior->ceof = -prior->ceof;
	    	prior = prior->next;
		}	
	}
    
    prior = head->next;
    free(head);//释放头结点
    
    
    return prior;
}

Polynomial PolynomialMultiplication(Polynomial p1,Polynomial p2){//多项式乘法 
    Polynomial p4 = NULL,prior = NULL,rear = NULL,head = NULL;//p4指向多项式首元结点,prior前驱指针,rear尾指针,head头指针
    Polynomial p22 = NULL,p11 = NULL;//遍历p1,p2

    head = (Polynomial)malloc(sizeof(PolyNode));
    head->next = NULL;//赋空
    prior = head;

    p11 = p1;
    p22 = p2;
    
   
    
    while(p22 && p11)//求p1第一项与多项式p2乘积之和
    {
    	cnt+=7; 
        rear = (Polynomial)malloc(sizeof(PolyNode));
        rear->next = NULL;
        rear->expon = p11->expon + p22->expon;
        rear->ceof = p11->ceof * p22->ceof;
        prior->next = rear;
        prior = prior->next;
        p22 = p22->next;
    }
    p4 = head->next;//第一个项乘法结果
    p11 = p11->next;//p1后面的项
   
    while(p11)//如果p1还有项,继续乘p2并与前项求和
    {
        p22 = p2;
        prior = head;
        while(p22)//p2多项式
        {
            cnt+=7;
            rear = (Polynomial)malloc(sizeof(PolyNode));
            rear->next = NULL;//一定要把下一个指针赋为NULL
            rear->expon = p11->expon + p22->expon;//指数加
            rear->ceof = p11->ceof * p22->ceof;//系数乘
            prior->next = rear;
            prior = prior->next;
            p22 = p22->next;
        }
        p11 = p11->next;//继续求p1后面的项
        p4 = PolynomialAdd(p4,head->next);//将p1的后几项与p2的乘积的到的多项式,与p4相加
    }
    free(head);
    
    
    return p4;
    
}

double PrintSum(Polynomial p1,double x){//求多项式的值 并返回 
	double sum;
	while(p1)
	{
		cnt+=2;
		sum+=p1->ceof * pow(x,(double)p1->expon);//运算量较大 
		p1 = p1->next;
	}
	printf("多项式的值为:%lf\n",sum); 
	return sum; 
}

void DestroyPolynomial(Polynomial p){//销毁多项式链表
    Polynomial l;
    while(p)
    {
        l = p->next;
        free(p);
        p = l;
    }
}

void PutTwoPoly(void){//输出两个多项式 
	Polynomial p1,p2;
	char filename1[30] ={"Polynomial1.txt"};//打开多项式1文件,文件要与.cpp文件放在同一个文件夹里,或这写出完整路径
    char filename2[30] ={"Polynomial2.txt"};//打开多项式2文件
	
	p1 = GetPolynomial(filename1);//获取多项式1
    p2 = GetPolynomial(filename2);
    
	printf("多项式1:\n\n");
    PrintPolynomial(p1);//打印多项式
    
    printf("\n多项式2:\n\n"); 
    PrintPolynomial(p2);
    
    DestroyPolynomial(p1);//销毁p1,p2;
    DestroyPolynomial(p2);
}

Polynomial GetDerivation(Polynomial p1){ //求导 
	Polynomial same = NULL,head = p1;
	
	
	while(p1){ 
		cnt+=4;//计算基本语句 
		
		if(p1->ceof){//第一项可能指数为0 
			p1->ceof*=p1->expon;//求系数 
			p1->expon--;	//求指数 
		}else {
			same = p1;
			p1 = p1->next;
			head = p1;//指数递增存放 
			free(same);
		}
		p1 = p1->next;		
	}
	
	
	return head;	
}

Polynomial GetIntegral(Polynomial p1){//求多项式的不定积分
	Polynomial head = p1;
	
	while(p1){
		cnt+=4; 
		p1->expon++;
		p1->ceof/=p1->expon;
		p1 = p1->next;
	} 
    
	return head;
}

void testAdd(void){//测试加法 
	Polynomial p1,p2,p3;
	
	char filename1[30] ={"Polynomial1.txt"};//打开多项式1文件,文件要与.cpp文件放在同一个文件夹里,或这写出完整路径
    char filename2[30] ={"Polynomial2.txt"};//打开多项式2文件
    char filename3[30] = {"Add.txt"}; //存加法结果
	 
    p1 = GetPolynomial(filename1);//获取多项式1
    p2 = GetPolynomial(filename2);
   
    start = clock();
    cnt = 0;//基本操作置为0 
	 
    p3 = PolynomialAdd(p1,p2);//p3采用整合获取多项式的和,会改变p1p2的
  
    stop=clock(); //记录结束时间
	duration=((double)(stop-start))/CLK_TCK;
	
	fprintf(time_file,"加法:\n"); //将时间消耗输入到文件里 
    fprintf(time_file,"ticksl = %lf	\n",(double)(stop-start)) ;
    
    fprintf(time_file,"time1=%6.2e\n",duration);
    fprintf(time_file,"基本操作次数: %d\n\n",cnt); //将时间消耗输入到文件里 
    
    PrintInformationTofile(filename3,p3); //打印计算结果到文件 
  
    printf("\n加法运行成功\n\n"); 
	
	//DestroyPolynomial(p1);
    //DestroyPolynomial(p2);//销毁p1,p2,整合到了p3里 
    DestroyPolynomial(p3);
    
    
}

void testSub(void){
	Polynomial p1,p2,p3;
	
	char filename1[30] = {"Polynomial1.txt"};//打开多项式1文件,文件要与.cpp文件放在同一个文件夹里,或这写出完整路径
    char filename2[30] = {"Polynomial2.txt"};//打开多项式2文件
    char filename3[30] = {"Sub.txt"}; 
    
    p1 = GetPolynomial(filename1);//获取多项式1
    p2 = GetPolynomial(filename2);
   
    start = clock(); 
    cnt= 0;//基本操作 次数置为0 
    
    p3 = PolynomialSub(p1,p2);//p3采用整合获取多项式的差,会改变p1p2的
    
    stop=clock(); //记录结束时间
	duration=((double)(stop-start))/CLK_TCK;
	
	fprintf(time_file,"减法:\n"); //将时间消耗输入到文件里 
    fprintf(time_file,"ticksl = %lf	\n",(double)(stop-start)) ;
    
    fprintf(time_file,"time1=%6.2e\n",duration);
    fprintf(time_file,"基本操作次数: %d\n\n",cnt); //将时间消耗输入到文件里 
    
    PrintInformationTofile(filename3,p3);//打印结果到文件中 
	printf("减法运行成功\n\n"); 

	
    //DestroyPolynomial(p1);//p1,p2在整合中已经被销毁 
    //DestroyPolynomial(p2);
    DestroyPolynomial(p3); 
    
}

void testMultiplication(void){
	Polynomial p1,p2,p3;
	
	char filename1[30] = {"Polynomial1.txt"};//打开多项式1文件,文件要与.cpp文件放在同一个文件夹里,或这写出完整路径
    char filename2[30] = {"Polynomial2.txt"};//打开多项式2文件
    char filename3[30] = {"Multiplication.txt"};\
    
    p1 = GetPolynomial(filename1);//获取多项式1
    p2 = GetPolynomial(filename2);
   
    start = clock();
    cnt = 0;//基本操作次数置为 0 
    
    p3 = PolynomialMultiplication(p1,p2);//求p1和p2乘积
    
    stop=clock(); //记录结束时间
	duration=((double)(stop-start))/CLK_TCK;
	
	fprintf(time_file,"乘法:\n"); //将时间消耗输入到文件里 
    fprintf(time_file,"ticksl = %lf	\n",(double)(stop-start)) ;
    
    fprintf(time_file,"time1=%6.2e\n",duration);
    fprintf(time_file,"基本操作次数: %d\n\n",cnt); //将时间消耗输入到文件里 
    
    PrintInformationTofile(filename3,p3);//打印结果到文件中 
    
    printf("乘法运行成功\n\n"); 
    
    DestroyPolynomial(p1);//销毁
    DestroyPolynomial(p2);
    DestroyPolynomial(p3);
   
}

void testSum(void){//求值测试 
	FILE *fp = NULL;
	Polynomial p1,p2;
	double x;//未知元 
	
	char filename1[30] = {"Polynomial1.txt"};//打开多项式1文件,文件要与.cpp文件放在同一个文件夹里,或这写出完整路径
    char filename2[30] = {"Polynomial2.txt"};//打开多项式2文件
    char filename3[30] = {"SumofPoly.txt"};// 
    
    fp = fopen(filename3,"w");
    
    p1 = GetPolynomial(filename1);//获取多项式1
    
	printf("请输入x的值:");
	while(!scanf("%lf",&x)){//健壮性 
		fflush(stdin);//清空输入缓冲区 
		printf("输入错误,请重新输入\n");
	}
	
	start = clock();
	cnt = 0;
	
    fprintf(fp,"多项式1 x的值为: %lf,带入求得的多项式1的值为:%lf\n",x,PrintSum(p1,x)); //打印多项式1的值到文件里 
    
    stop=clock(); //记录结束时间
	duration=((double)(stop-start))/CLK_TCK;
	
	fprintf(time_file,"求多项式1的值:\n"); //将时间消耗输入到文件里 
    fprintf(time_file,"ticksl = %lf	\n",(double)(stop-start)) ;
    
    fprintf(time_file,"time1=%6.2e\n",duration);
    fprintf(time_file,"基本操作次数: %d\n\n",cnt); //将时间消耗输入到文件里
  
    
    p2 = GetPolynomial(filename2);//获取多项式2并储存在链表中 
    printf("请输入x的值:");
    
	while(!scanf("%lf",&x)){
		fflush(stdin); 
		printf("输入错误,请重新输入\n");
	}
	
	start = clock();
	cnt = 0;
	
    fprintf(fp,"多项式2 x的值为: %lf,带入求得的多项式2的值为:%lf\n",x,PrintSum(p2,x)); //打印多项式1的值到文件里 
	
	stop=clock(); //记录结束时间
	duration=((double)(stop-start))/CLK_TCK;
	
	fprintf(time_file,"求多项式2的值:\n"); //将时间消耗输入到文件里 
    fprintf(time_file,"ticksl = %lf	\n",(double)(stop-start)) ;
    
    fprintf(time_file,"time1=%6.2e\n",duration);
    fprintf(time_file,"基本操作次数: %d\n\n",cnt); //将时间消耗输入到文件里
	printf("\n求值测试运行成功\n");
	
    DestroyPolynomial(p1);//销毁p1,p2,p3
    DestroyPolynomial(p2);
 	
    fclose(fp);
}

void testDerivation(void){//测试求导 
	Polynomial p1,p2;
	char filename1[30] = {"Polynomial1.txt"};//打开多项式1文件,文件要与.cpp文件放在同一个文件夹里,或这写出完整路径
    char filename2[30] = {"Polynomial2.txt"};//打开多项式2文件
    char filename3[30] = {"Derivation.txt"};
    
    p1 = GetPolynomial(filename1);//获取多项式1
    p2 = GetPolynomial(filename2);//获取多项式2 
    
    cnt = 0;
    start = clock();
    
    p1 = GetDerivation(p1);//求导 
    
    stop=clock(); //记录结束时间
	duration=((double)(stop-start))/CLK_TCK;
	
	fprintf(time_file,"对多项式1求导:\n"); //将时间消耗输入到文件里 
    fprintf(time_file,"ticksl = %lf	\n",(double)(stop-start)) ;
    
    fprintf(time_file,"time1=%6.2e\n",duration);
    fprintf(time_file,"基本操作次数: %d\n\n",cnt); //将时间消耗输入到文件里
    
    PrintInformationTofile(filename3,p1);//打印结果到文件中 
    
    cnt = 0;
    start = clock();

    p2 = GetDerivation(p2);//求导 
    
    stop=clock(); //记录结束时间
	duration=((double)(stop-start))/CLK_TCK;
	
	fprintf(time_file,"对多项式2求导:\n"); //将时间消耗输入到文件里 
    fprintf(time_file,"ticksl = %lf	\n",(double)(stop-start)) ;
    
    fprintf(time_file,"time1=%6.2e\n",duration);
    fprintf(time_file,"基本操作次数: %d\n\n",cnt); //将时间消耗输入到文件里
    
   	PrintInformationTofile(filename3,p2);//打印结果到文件中 
   
    DestroyPolynomial(p1);//销毁p1,p2,p3
    DestroyPolynomial(p2);
 
    printf("\n求导测试成功\n");
}

void testIntegral(void){//求定积分测试
	Polynomial p1,p2;
	char filename1[30] = {"Polynomial1.txt"};//打开多项式1文件,文件要与.cpp文件放在同一个文件夹里,或这写出完整路径
    char filename2[30] = {"Polynomial2.txt"};//打开多项式2文件
    char filename3[30] = {"Integral.txt"}; 
    
    p1 = GetPolynomial(filename1);//获取多项式1
    
    cnt = 0;//基本操作数置为0 
	start = clock();//获取起始时间 
	 
    p1 = GetIntegral(p1);//对多项式1求不定积分 
    
    stop=clock(); //记录结束时间
	duration=((double)(stop-start))/CLK_TCK;
	
	fprintf(time_file,"多项式1求不定积分:\n"); //将时间消耗输入到文件里 
    fprintf(time_file,"ticksl = %lf	\n",(double)(stop-start)) ;
    
    fprintf(time_file,"time1=%6.2e\n",duration);
    fprintf(time_file,"基本操作次数: %d\n\n",cnt); //将时间消耗输入到文件里
    
    PrintInformationTofile(filename3,p1);//打印结果到文件中 
    
    
    p2 = GetPolynomial(filename2);
    
    cnt = 0;
	start = clock();
	 
    p2 = GetIntegral(p2);//对多项式2求积分 
    
    stop = clock();
    duration=((double)(stop-start))/CLK_TCK;
    
    fprintf(time_file,"多项式2求不定积分:\n"); //将时间消耗输入到文件里 
    fprintf(time_file,"ticksl = %lf	\n",(double)(stop-start)) ;
    
    fprintf(time_file,"time1=%6.2e\n",duration);
    fprintf(time_file,"基本操作次数:%d\n\n",cnt); //将时间消耗输入到文件里
    
	PrintInformationTofile(filename3,p2);//打印结果到文件中 
   
    DestroyPolynomial(p1);//销毁p1,p2,p3
    DestroyPolynomial(p2);
 
    printf("\n求不定积分测试成功\n");
} 
int main(){
	time_file = fopen("time_analyze.txt","w");//打开时间分析文件 
	
	CreateInformation();//生成 一元多项式并输入到文件中 
    //PutTwoPoly();//输出多项式1,2 
   
	testAdd();//加法 
	testSub(); //减法 
	
	testMultiplication();//乘法 
	testSum();//求值 
	
	testDerivation();//求导
	testIntegral();//求不定积分 

	fclose(time_file);//关闭时间分析文件 
    return 0;
}
 /* 
多项式1 
5 8
2 3
1 6
1 5
多项式2
3 2
10 5
3 4
6 3
5 9
-1 6
*/
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值