1. 程式人生 > >資料結構——一元多項式的運算(相加,相減,相乘)【C語言實現】

資料結構——一元多項式的運算(相加,相減,相乘)【C語言實現】

實現一元多項式的運算(相加,相減,相乘)

1.輸入多項式時無論以何種順序輸入,都能夠以升冪順序輸出,且有相同指數項時能夠合併。 2.實現相加,相減,相乘功能。 3.能夠代入確切的X的值求取最終多項式的值。

#include<stdio.h>
#include<stdlib.h>
#include<math.h> 

#define LEN sizeof(Poly)

typedef struct term{
	float coef;		//係數 
	int expn;		//指數 
	struct term *next;
}Poly,*Link;
int LocateElem(Link p, Link s, Link &q); 
void CreatePolyn(Link &p,int m);	//建立多項式 
void PrintPolyn(Link p);			//列印多項式(表示)			
int cmp(Link a, Link b);
Link AddPolyn(Link pa, Link pb);	//多項式相加 
Link SubPolyn(Link pa, Link pb);	//多項式相減 
Link Reverse(Link p);				//逆置多項式 
Link MultiplyPolyn(Link A,Link B);	//多項式相乘 
void Calculate(Link p,float x);		//多項式求值 

int main()
{
	Link P1,P2,P3;	//多項式 
	int L1,L2;		//多項式長度 
	printf("                        -------------------------------------------------------------------\n");
	printf("                        |==================       一元多項式的運算       =================|\n");
	printf("                        |==================          1.相加(+)         =================|\n");
	printf("                        |==================          2.相減(-)         =================|\n");
	printf("                        |==================          3.相乘(*)         =================|\n");
	printf("                        -------------------------------------------------------------------\n\n");
	printf("請輸入第一個多項式的項數:");
	scanf("%d",&L1);
	CreatePolyn(P1,L1);
	printf("第一個多項式為:");
	printf("P1(X)=");
	PrintPolyn(P1);
	printf("請輸入第二個多項式的項數:");
	scanf("%d",&L2);
	CreatePolyn(P2,L2);
	printf("第二個多項式為:");
	printf("P2(X)=");
	PrintPolyn(P2); 
	printf("\n");
	
	printf("請輸入要選擇的運算(+ , - , *): ");
	char ch1;
	getchar();		//清除掉緩衝區的回車符 
	scanf("%c",&ch1);
	getchar();		//清除掉緩衝區的回車符
 	switch(ch1){
	 	case '+':{
	 		printf("兩個一元多項式相加:   ");
	 		printf("P1(X)+P2(X)=");
	 		P3=AddPolyn(P1, P2);
			PrintPolyn(P3);
	 	}break;
	 	case '-':{
	 		printf("兩個一元多項式相減:   ");
	 		printf("P1(X)-P2(X)=");
	 		P3=SubPolyn(P1, P2);
			PrintPolyn(P3);
	 	}break;
	 	case '*':{
	 		printf("兩個一元多項式相乘:   ");
	 		printf("P1(X)*P2(X)=");
	 		P3=MultiplyPolyn(P1, P2);
			PrintPolyn(P3);
	 	}break;
	 	default:printf("您輸入了錯誤指令 %c !",ch1); 
	 }

	char ch2;
	printf("\n是否代入X進行求值?(Y/N): ");
	ch2=getchar();		//清除掉緩衝區的回車符  
	getchar();
	switch(ch2){
		case 'Y':{
			float x;
			printf("\n請輸入多項式中X的值:");
			scanf("%f",&x); 
			Calculate(P3,x);
			break;	
		}
		case 'N':break;
		default:printf("你輸入了錯誤指令 %c !",ch2); 
	} 
	return 0;
}

int LocateElem(Link p, Link s, Link &q){
/*遍歷連結串列p,每一個結點與s比較指數,
若相同,q指向相同指數項的結點,返回1,
若不相同,根據s所指指數大小在連結串列p中的位置來確定q的指向結點,返回0 
*/ 
	Link p1 = p->next;
	Link p2 = p;
	while(p1){
		if(s->expn > p1->expn){
			p1 = p1->next;
			p2 = p2->next;
		}else if(s->expn == p1->expn){
			q = p1; 
			return 1;
		}else{
			q = p2;
			return 0;
		}
	}
	if(!p1){
		q = p2;
		return 0;
	}
}

void CreatePolyn(Link &p,int m) 
/*建立帶頭結點的連結串列(多項式) 
且無論按什麼順序輸入,或是有相同指數項
最終在多項式中都是升冪順序! 
*/
{
	Link s,q;
	int i;
	p=(Link)malloc(LEN);
	p->next=NULL;
	for(i=0;i<m;i++)
	{
		s=(Link)malloc(LEN);
		printf("輸入係數和指數(以空格隔開):");
		scanf("%f %d", &s->coef, &s->expn);
		if(!LocateElem(p, s, q)){	//若沒有相同指數項,則鏈入 
			s->next = q->next;
			q->next = s;
		}else{						//若有相同指數項,則係數相加						
			q->coef+=s->coef;
		}
	}
	
}

void PrintPolyn(Link p)
//列印顯示多項式 
{
	Link s;
	s = p->next;
	while(s)
	{
	        printf(" %.2f X^%d", s->coef, s->expn);
            s = s->next;
            if(s!=NULL)  
                if(s->coef>=0) printf(" +");
				//若下一項係數為正,則列印'+',否則不列印 
	}
	printf("\n");
}

int cmp(Link a, Link b)
//比較兩結點指數大小,根據情況返回不同值 
{
	if (a->expn<b->expn) return  -1;
	else if(a->expn == b->expn) return  0;
	else return 1;
}

Link AddPolyn(Link pa, Link pb)//pa,pb均指向頭結點 
//兩個多項式相加得一個新多項式,並且返回新多項式的頭結點的指標   
{
	Link newp, p, q, s, pc;
	float sum;
	p = pa->next; 
	q = pb->next;
	newp=(Link)malloc(LEN); //新多項式的頭結點 
	pc = newp;	//pc指向新多項式的頭結點
	while(p&&q){
		switch(cmp(p, q))
		{
			case -1:// //若指數:p<q,則將p所指結點鏈入頭結點為newp的連結串列中,且p向後遍歷   
				s = (Link)malloc(LEN); 
				s->coef = p->coef;
				s->expn = p->expn;
				pc->next = s;
				pc = s;
				p = p->next;
				break;
			case 0://若比較兩項的指數相等,則將兩項係數相加後得到的項放入頭結點為newp的連結串列中 ,且p,q同時向後遍歷  
				sum = p->coef+q->coef; 
				if(sum!=0.0)//若兩項係數相加為0,則不放入頭結點為newp的連結串列中
				{
					s = (Link)malloc(LEN);
					s->coef = sum;
					s->expn = p->expn;
					pc->next = s;
					pc = s;
				}
				p = p->next;
				q = q->next;
				break;
			case 1://若指數:q<p,則將q所指結點鏈入頭結點為newp的連結串列中,且q向後遍歷    
				s = (Link)malloc(LEN);
				s->coef = q->coef;
				s->expn = q->expn;
				pc->next = s;
				pc = s;
				q = q->next;
				break;
		}
	}
	pc->next=p?p:q;//鏈入pa或pb的剩餘項 
	return newp;//返回新多項式的頭指標 
}
Link SubPolyn(Link pa, Link pb)
/*兩個多項式相減得一個新多項式,並且返回新多項式的頭結點的指標
相減就是先將減數中每一項的係數變為負,再將兩個多項式相加 
*/ 
{
	Link newp, p, q, s, pc;
	float sum;
	newp=(Link)malloc(LEN); 
	pc = newp;
	p = pa->next; 
	q = pb->next;
	while(q){// 將pb中每一項的係數變為負 
		q->coef=0-q->coef;
		q=q->next;
	}
	q=pb->next;
	while(p&&q){
		switch(cmp(p, q))
		{
			case -1:  
				s = (Link)malloc(LEN); 
				s->coef = p->coef;
				s->expn = p->expn;
				pc->next = s;
				pc = s;
				p = p->next;
				break;
			case 0: 
				sum = p->coef-q->coef; 
				if(sum!=0.0)
				{
					s = (Link)malloc(LEN);
					s->coef = sum;
					s->expn = p->expn;
					pc->next = s;
					pc = s;
				}
				p = p->next;
				q = q->next;
				break;
			case 1:    
				s = (Link)malloc(LEN);
				s->coef = q->coef;
				s->expn = q->expn;
				pc->next = s;
				pc = s;
				q = q->next;
				break;
		}
	}
	pc->next=p?p:q;
	return newp;
}
Link Reverse(Link p)
/*用頭插法逆置連結串列,
使多項式由降冪變成升冪順序
或使多項式由升冪變成降冪順序
*/ 
{
	Link head=p; 
	Link q1,q2;
    q2=head->next;
    head->next=NULL;//斷開頭結點與第一個結點 
    while(q2)
    {
        q1=q2;      
        q2=q2->next; 
		q1->next=head->next; //頭插 
		head->next=q1;  
    }      
    return head;//返回連結串列逆置後的頭結點 
}
Link MultiplyPolyn(Link A,Link B)
/*兩個多項式相乘得一個新多項式,並且返回新多項式的頭結點的指標
	相乘前,A,B兩個多項式均是升冪排序 
	相乘時,A為降冪排序,B為升冪排序  
*/
{
  Link pa,pb,pc,s,head;
  int k,maxExpn,minExpn;
  float coef;
  
  head=(Link)malloc(LEN);//頭結點 
  head->next=NULL;
  
  if(A->next!=NULL&&B->next!=NULL){
  	minExpn=A->next->expn+B->next->expn; //minExpn為兩個多項式中指數和的最小值 
 	A=Reverse(A);//將A降冪排列 
	B=Reverse(B);//將B降冪排列 
  	maxExpn=A->next->expn+B->next->expn; //maxExpn為兩個多項式中指數和的最大值
  }
  else{
	  	return head;
  }       
   pc=head;
   B=Reverse(B);//將B升冪排列 
   
   for(k = maxExpn;k>=minExpn;k--){ //多項式的乘積指數範圍為:minExpn~maxExpn
   		//根據兩項的指數和使每一次迴圈都得到新多項式中一項  
   		pa = A->next;
   		while(pa !=NULL&&pa->expn>k){  //找到pa的位置 
		   	pa = pa->next;
		   }
   		pb = B->next;
   		while(pb!=NULL&&pa!=NULL&&pa->expn+pb->expn<k){//如果指數和和小於k,pb後移結點 
		   	pb = pb->next;
		   }
		coef=0.0;
		while(pa!=NULL&&pb!=NULL){
			if(pa->expn+pb->expn==k){ //如果指數和等於k,係數和累加,且pa,pb均後移結點 
				coef+=pa->coef*pb->coef;
                pa=pa->next;
                pb=pb->next;
			}
			else if(pa->expn+pb->expn>k){//如果指數和大於k,pb後移結點
				pa = pa->next;
			}
			else{//如果指數和和小於k,pb後移結點
					pb = pb->next;
			}	
		}
		if(coef!=0.0){
		//如果係數和不為0,則生成新結點,將係數和指數賦給新結點後插入到新多項式中 
			s=(Link)malloc(LEN);
            s->coef=coef;
            s->expn=k;
            s->next=pc->next;
            pc->next=s;
            pc=s;
		}
   }
   B = Reverse(B);
   head=Reverse(head);
   return head;	//返回新多項式的頭結點 
}
void Calculate(Link p,float x)
//代入確定的x到多項式中求值 
{
	Link q=p->next;
	float sum;
	float result=0;//求的結果 
	while(q){
		sum=1.0;
		for(int i=1;i<=q->expn;i++){//先求每一項的 X^expn 的值 
				sum=sum*x;
		}
		result+=sum*q->coef; //再使係數與sum相乘後求每一項的值,最後累加
		q=q->next; 
	}
	printf("將X的值代入多項式中計算的結果為:%.5f\n",result);
} 

相加: 在這裡插入圖片描述

相乘: 在這裡插入圖片描述