大作业 多项式 纯链表实现

之前的多项式本质是数组实现的,而且转换了好几次,受内存空间限制,更难过的是又发现了不能正确算带小数系数的多项式的bug,修了一个小时无果。
在一个月黑风高的夜晚,三千五跑完后偶遇求计学长,一番指点后决定重写。
一个一个读入,边读边判断,重写了一下排序函数,现在可以了!

//多项式加减乘
//输入格式:x前面为系数,后面为次数 ;不必按次数输入,可打乱,可有空格(会过滤空格) 
//例如:x5+2x3+2 表示x的五次方+2*x的三次方+2
//输出格式:指数递增,正常格式 如上例:2.00+2.00x^3+x^5
//BY Peter_H 
//2019.4.5 21:30--24:30 
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
typedef struct node* ptr;
struct node{
	int ex;
	double coef;
	ptr next;
};//存多项式

int isop(char ch)//判断操作符 
{
	if(ch=='+')return 1;
	else if(ch=='-')return -1;
	else if(ch=='*')return 2;
	else return 0;
}
ptr createpoly()//创建链表存多项式边读边判断
{
	ptr ans,tmp,p;
	char ch;
	p=(ptr)malloc(sizeof(struct node));
	p->next=NULL;
	ans=p;
	ch=getchar();
	char d[1000]={'\0'};
	int k=0,flag=1;
	while(ch!='\n')
	{
		while(ch==' ')
		{
			ch=getchar();
			continue;
		}
		while(ch=='.'||isdigit(ch)){
			d[k++]=ch;
			ch=getchar();
			while(ch==' ')
			{
				ch=getchar();
				continue;
			}
		}
		if(isop(ch))
		{
			if(k)
			{
			 	tmp=(ptr)malloc(sizeof(struct node));
				tmp->next=NULL;
				tmp->coef=flag*atof(d);
				flag=1;
				tmp->ex=0;
				p->next=tmp;
				p=p->next;
				memset(d,'\0',sizeof(d));
				k=0;
			}//1.5+...
			if(ch=='-')flag=-1;
			else if(ch=='+')flag=1;
			ch=getchar();
		
		}
		if(ch=='x')
		{
			if(k==0)
			{
				tmp=(ptr)malloc(sizeof(struct node));
				tmp->next=NULL;
				tmp->coef=flag;
				flag=1;
				ch=getchar();
				while(ch==' ')
				{
					ch=getchar();
					continue;
				}
				if(isop(ch))//x+...
				{
					if(ch=='-')flag=-1;
					else if(ch=='+')flag=1;
					tmp->ex=1;
					p->next=tmp;
					p=p->next;
				}
				else if(isdigit(ch)) //x2+...
				{
					tmp->ex=ch-'0';
					p->next=tmp;
					p=p->next;
				}
				else if(ch=='\n')//x
				{
					tmp->ex=1;
					p->next=tmp;
					p=p->next;
					break;
				}
				ch=getchar();
			}
			else//1.5x2+...
			{
				tmp=(ptr)malloc(sizeof(struct node));
				tmp->next=NULL;
				tmp->coef=flag*atof(d);
				flag=1;
				memset(d,'\0',sizeof(d));
				k=0;
				ch=getchar();
				while(ch==' ')
				{
					ch=getchar();
					continue;
				}
				if(isop(ch))
				{
					if(ch=='-')flag=-1;
					else if(ch=='+')flag=1;
					tmp->ex=1;
					p->next=tmp;
					p=p->next;
				}
				else if(isdigit(ch))//1.5x2
				{
					tmp->ex=ch-'0';
					p->next=tmp;
					p=p->next;
				}
				else if(ch=='\n')//1.5x
				{
					tmp->ex=1;
					p->next=tmp;
					p=p->next;
					break;
				}
				ch=getchar();
			}
		}
		if(ch=='\n'&&k)
		{
  		    tmp=(ptr)malloc(sizeof(struct node));
			tmp->next=NULL;
			tmp->coef=flag*atof(d);
			flag=1;
			tmp->ex=0;
			p->next=tmp;
			p=p->next;
			memset(d,'\0',sizeof(d));
			k=0;
		}
	}
	return ans;
}
void sortpoly(ptr poly)//从小到大排序 冒泡排 
{
	ptr q,p;
	q=poly->next;
	if(q)p=q->next;
	while(q)
	{
		while(p)
		{
			if(q->ex>p->ex)
			{
				int tmp2;
				double tmp1;
				tmp1=q->coef;
				q->coef=p->coef;
				p->coef=tmp1;
				tmp2=q->ex;
				q->ex=p->ex;
				p->ex=tmp2;
			}
			p=p->next;
		}
		
		q=q->next;
		if(q)p=q->next;
	}
	//合并系数 
	ptr pp=poly->next;
	while(pp)
	{
		if(pp->next)
		{
			if(pp->ex==pp->next->ex)
			{
				ptr q=pp;
			    while(pp->next&&q->ex==pp->next->ex)
				  {
				  		pp=pp->next;		  	
				  		q->coef+=pp->coef; 
				  }
				  pp=pp->next;
				  q->next=pp; 
						
			}
		 	else pp=pp->next; 
		}
		else pp=pp->next;
		
	}
	//删除0项 
	ptr ppp=poly->next;
	while(ppp)
	{
		if(ppp->next==NULL&&ppp->coef==0)poly->next=NULL;
		else if(ppp->next&&ppp->next->coef==0)
		{
			ptr tmp=(ptr)malloc(sizeof(struct node));
			tmp=ppp->next;
			ppp->next=tmp->next;
			free(tmp);
		}
		if(ppp)ppp=ppp->next;
	}
	
}

void printpolynode(ptr p)//输出多项式链表 
{
	if(p->next)p=p->next;
	else{
		printf("0.00\n");
		return;
	} 
	if(p){
		if(p->coef!=-1&&p->coef!=1&&p->ex>1)printf("%.2lfx^%d",p->coef,p->ex);
		else if(p->coef==1&&p->ex>1)printf("x^%d",p->ex);
		else if(p->coef==-1&&p->ex>1)printf("-x^%d",p->ex);
		else if(p->coef!=-1&&p->coef!=1&&p->ex==1)printf("%.2lfx",p->coef);
		else if(p->coef==1&&p->ex==1)printf("x");
		else if(p->coef==-1&&p->ex==1)printf("-x");
		else if(p->ex==0)printf("%.2lf",p->coef);	
		p=p->next;	
	}
	for(;p;p=p->next)
 	{
 		if(p->coef>1&&p->ex>1)
	  	     printf("+%.2lfx^%d",p->coef,p->ex);
 		else if(p->coef>1&&p->ex==1)
 			 printf("+%.2lfx",p->coef);
 		else if(p->coef==1&&p->ex>1)
 			 printf("+x^%d",p->ex);
 		else if(p->coef==1&&p->ex==1)
 			 printf("+x");
 		else if(p->coef<-1&&p->ex>1)
 			 printf("%.2lfx^%d",p->coef,p->ex);
 		else if(p->coef<-1&&p->ex==1)
 			 printf("%.2lfx",p->coef);
 		else if(p->coef==-1&&p->ex>1)
 			 printf("-x^%d",p->ex);
 		else if(p->coef==-1&&p->ex==1)
 			 printf("-x");
	    else if(p->ex==0)
	    {
	    	if(p->coef>0)printf("+%.2lf",p->coef);
	    	else if(p->coef<0)printf("%.2lf",p->coef);
		}
    }
    printf("\n");
}

ptr addpoly(struct node*p1,struct node*p2)//多项式加法 
{
	//printf("多项式加减法。\n");
	ptr p,ans,pp1,pp2;
	pp1=p1->next;
	pp2=p2->next;
	p=(ptr)malloc(sizeof(struct node));
	p->next=NULL;
	ans=p;
	while(pp1&&pp2)
	{
		//printf("$$%d %d$$\n",p->coef,p->ex);
		if(pp1->ex<pp2->ex){
			ptr tmp=(ptr)malloc(sizeof(struct node));
			tmp->next=NULL;
			tmp->coef=pp1->coef;
			tmp->ex=pp1->ex;
			p->next=tmp;//这里如果不弄tmp 直接p->next=pp1 后面可能会把pp1改掉 
			p=p->next;
			pp1=pp1->next;
		}
		else if(pp1->ex>pp2->ex)
		{
		    ptr tmp=(ptr)malloc(sizeof(struct node));
			tmp->next=NULL;
			tmp->coef=pp2->coef;
			tmp->ex=pp2->ex;
			p->next=tmp;
			p=p->next;
			pp2=pp2->next;
		}
		else{
			ptr tmp=(ptr)malloc(sizeof(struct node));
			tmp->next=NULL;
			tmp->coef=pp1->coef+pp2->coef;
			tmp->ex=pp1->ex;
			if(tmp->coef){
				p->next=tmp;
				p=p->next;
				pp1=pp1->next;
				pp2=pp2->next; 
			}
			else {
				free(tmp);
			//	p=p->next;
				pp1=pp1->next;
				pp2=pp2->next; 
			}
		}
	}
	if(pp1)p->next=pp1;
	if(pp2)p->next=pp2;
	return ans;
}
ptr substractpoly(struct node*p1,struct node*p2)//多项式减法 为poly1-poly2 首先把poly2变成相反数 然后调用加法 
{
	ptr mp2,ans;
	mp2=(ptr)malloc(sizeof(struct node));
	mp2->next=NULL;
	ans=mp2;
	if(p1->next==NULL&&p2->next==NULL)return ans;
	p2=p2->next;
	while(p2)
	{
		ptr tmp=(ptr)malloc(sizeof(struct node));
		tmp->next=NULL;
		tmp->coef=-p2->coef;
		tmp->ex=p2->ex;
		mp2->next=tmp;
		p2=p2->next;
		mp2=mp2->next;
	}
	
	return addpoly(p1,ans);
}
ptr multipoly(struct node*p1,struct node*p2)//多项式乘法 先乘一组,然后再乘后面的,插入 
{
	//printf("多项式乘法。\n");
	ptr phead,p,tmp,pp1,pp2,ans,pp2h;
	pp1=p1->next;
	pp2=p2->next;
	pp2h=pp2;
	p=(ptr)malloc(sizeof(struct node));
	p->next=NULL;
	ans=p;
	if(pp1==NULL||pp2==NULL)return p;
	while(pp2){
		ptr tmp=(ptr)malloc(sizeof(struct node));
		tmp->next=NULL;
		tmp->coef=pp1->coef*pp2->coef;
		tmp->ex=pp1->ex+pp2->ex;
		p->next=tmp;
		p=p->next;
		pp2=pp2->next;
	}
	pp1=pp1->next;
	while(pp1)
	{
		pp2=pp2h;
		while(pp2)
		{
			ptr tmp=(ptr)malloc(sizeof(struct node));
			tmp->next=NULL;
			tmp->coef=pp1->coef*pp2->coef;
			tmp->ex=pp1->ex+pp2->ex;
			ptr q1=ans,q=q1->next;
			while(q&&q->ex<tmp->ex)
				{
					q=q->next;
					q1=q1->next;
				}
			if(q)
			{
				if(q->ex==tmp->ex){
					q->coef+=tmp->coef;
					if(q->coef){
						pp2=pp2->next;	
						continue;				
					}
					else{
						q1->next=q->next;
						free(q);
					}
				}
			else  {
				tmp->next=q->next;
				q->next=tmp;	//插入		
			}
			}
			else {
				if(tmp->coef)
				{
					p->next=tmp;
					p=p->next;
				}
			}
			pp2=pp2->next;		
		}
		pp1=pp1->next;
		 
	}
	return ans;
	
}
int main()
{
	ptr poly1,poly2,padd,psubstract,pmulti;
	printf("这是一个多项式运算器。\n");
	printf("你可以用它来计算多项式加法、减法、乘法。系数默认保留两位小数。\n");
 	printf("例如:如果要输入x的三次方加2x的平方加3,直接输“x3+2x2+3”即可。\n");
	poly1=createpoly();
	poly2=createpoly();
	sortpoly(poly1);
	sortpoly(poly2);
	//printpolynode(poly1);
	//printpolynode(poly2);
	padd=addpoly(poly1,poly2);//多项式加法
	psubstract=substractpoly(poly1,poly2);//多项式减法 
	pmulti=multipoly(poly1,poly2);//多项式乘法 
	printf("两多项式相加得:\n");
	printpolynode(padd);
	printf("两多项式相减得:\n");
	printpolynode(psubstract);
	printf("两多项式相乘得:\n");
	printpolynode(pmulti);
	return 0;
}
	


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值