7.一元多项式相乘

问题描述

  中缀表达式就是我们通常所书写的数学表达式,后缀表达式也称为逆波兰表达式,在编译程序对我们书写的程序中的表达式进行语法检查时,往往就可以通过逆波兰表达式进行。我们所要设计并实现的程序就是将中缀表示的算术表达式转换成后缀表示,例如,将中缀表达式

(A 一 (B*C 十 D)*E) / (F 十 G )

转换为后缀表示为:ABC*D十E*--FG十/

注意:为了简化编程实现,假定变量名均为单个字母,运算符只有+,-,*,/ 和^(指数运算,要注意运算符的结合性),可以处理圆括号 (),并假定输入的算术表达式正确。

要求:使用栈数据结构实现 ,输入的中缀表达式以#号结束

输入

整数N。表示下面有N个中缀表达式
N个由单个字母和运算符构成的表达式

输出

N个后缀表达式。

我的第一种思路是获取可能得到的最大的指数max,然后从I等于0开始遍历到max,把i分为可以相加得到它的两个值,再在链表里去找这两个值

/* PRESET CODE BEGIN - NEVER TOUCH CODE BELOW */  
 
#include <stdio.h>  
#include <stdlib.h>  
/*
<1,0>,<2,1>,<1,2>,
<1,0>,<1,1>,
<-1,0>,<1,1>,
<1,0>,<1,1>,
<0,0>,
<0,0>,
*/
typedef struct node  
{   int    coef, exp;  
    struct node  *next;  
} NODE;  

void multiplication( NODE *, NODE * , NODE * );  
void input( NODE * );  
void output( NODE * );  
void input( NODE * head )  
{   int flag, sign, sum, x;  
    char c;  
  
    NODE * p = head;  
  
    while ( (c=getchar()) !='\n' )  
    {  
        if ( c == '<' )  
        {    sum = 0;  
             sign = 1;  
             flag = 1;  
        }  
        else if ( c =='-' )  
             sign = -1;  
        else if( c >='0'&& c <='9' )  
        {    sum = sum*10 + c - '0';  
        }  
        else if ( c == ',' )  
        {    if ( flag == 1 )  
             {    x = sign * sum;  
                  sum = 0;  
                  flag = 2;  
          		  sign = 1;  
             }  
        }  
        else if ( c == '>' )  
        {    p->next = ( NODE * ) malloc( sizeof(NODE) );  
             p->next->coef = x;  
             p->next->exp  = sign * sum;  
             p = p->next;  
             p->next = NULL;  
             flag = 0;  
        }  
    }  
}  
 
void output( NODE * head )  
{  
    while ( head->next != NULL )  
    {   head = head->next;  
        printf("<%d,%d>,", head->coef, head->exp );  
    }  
    printf("\n");  
}  

int main()  
{   NODE * head1, * head2, * head3;  
    head1 = ( NODE * ) malloc( sizeof(NODE) );  
    input( head1 );  
    head2 = ( NODE * ) malloc( sizeof(NODE) );  
    input( head2 );  
    head3 = ( NODE * ) malloc( sizeof(NODE) );  
    head3->next = NULL;  
    multiplication( head1, head2, head3 );  
  
    output( head3 );  
    return 0;  
}  
  void multiplication( NODE *head1, NODE * head2, NODE * head3){
  	int max1=-1,max2=-1;
  	NODE * p=head1->next;
	NODE * q=head2->next;
  	while(p!=NULL){
  		if(p->exp>max1){
  			max1=p->exp;
		  }
		p=p->next;
	  }
	while(q!=NULL){
  		if(q->exp>max2){
  			max2=q->exp;
		  }
		q=q->next;
	  }
	  
	  int max=max1+max2;
	  //printf("%d",max);//max是能得到的最大指数 
	  NODE *r=head3;
	  for(int i=0;i<max+1;i++){//找出结果中系数为i的 
	     NODE *m;
	     m = ( NODE * ) malloc( sizeof(NODE) );  
	  	 m->exp=i;
	  	 int xishu=0;
	  	 int flag=0;
	  	 for(int j=0;j<=i;j++){//得到i的每一项 
	  	 	NODE *s=head1->next;
	  	 	flag=0;
	  	 	int k;
	  	 	for( k=0;s->exp!=j&&k<max1;k++){
	  	 		s=s->next;
			   }
			   if(s->exp!=j){
			   	flag=1;
			   }//printf("flag=%d j=%d exp=%dcoef=%d\n",flag,j,s->exp,s->coef);
			NODE *t=head2->next;
			for( k=0;t->exp!=i-j&&k<max2;k++){
	  	 		t=t->next;//printf("mad\n");
			   }
			   if(t->exp!=i-j){
			   	flag=1;
			   }//printf("flag=%d j=%d exp=%dcoef=%d\n",flag,j,t->exp,t->coef);
			   if(flag==0){
			   	xishu+=(t->coef)*(s->coef);
			   }
			   	//printf("xishu=%d i=%d flag=%d\n",xishu,i,flag);
			   //printf("%d\n",xishu);
		   }
		if(xishu!=0){
			m->coef=xishu;
		r->next=m;
	  	r=m;
		}
		
		 
	  }
	  r->next=NULL;
  	
  }
/* PRESET CODE END - NEVER TOUCH CODE ABOVE */  

这个做法可以把所有的非隐藏案例过了,但是隐藏案例显示内存RE了,所以我尝试另一种方法,先建一个数组将每一项依次相乘,将得到的答案先存入数组中,再利用数组建表。

但是面对的第一个问题就是数组只能做到自然数,负数没有位子。所以要再建一个数组处理负数的

int zhengshu[10010],fushu[10010];  
 void multiplication( NODE *head1, NODE * head2, NODE * head3){
 	int max1=-1,max2=-1;
  	NODE * p=head1->next;
	NODE * q=head2->next;
  	while(p!=NULL){
  		if(p->exp>max1){
  			max1=p->exp;
		  }
		p=p->next;
	  }
	while(q!=NULL){
  		if(q->exp>max2){
  			max2=q->exp;
		  }
		q=q->next;
	  }
	  
	  int max=max1+max2;
	  //printf("%d",max);//max是能得到的最大指数 
	memset(zhengshu,0,sizeof(zhengshu));
	memset(fushu,0,sizeof(fushu));
	p=head1;
	q=head2;
	while(p->next!=NULL){
		p=p->next;
		q=head2;
		while(q->next!=NULL){//1个p找n个q相乘 
			q=q->next;
			int xishu=p->coef*q->coef;
			int zhishu=p->exp+q->exp;
			if(zhishu>=0){
				zhengshu[zhishu]+=xishu;
			}
			else{
				fushu[-1*zhishu]+=xishu;
			}
		}}
		int fu=0;
		for(int i=0;i<10010;i++){
			if(fushu[i]!=0){
				fu=i;
			}
		}
		if(fu!=0){//有负数部分 
			NODE *r=head3;
		
	     for(int i=fu;i>0;i--){
			if(fushu[i]!=0){
				NODE *m;
	    		m = ( NODE * ) malloc( sizeof(NODE) );
	    		m->exp=i*-1;
	    		m->coef=fushu[i];
	    		r->next=m;
	    		r=m;
			}   
		 }
		 for(int i=0;i<=max;i++){
		 	if(zhengshu[i]!=0){
		 		NODE *m;
	    		m = ( NODE * ) malloc( sizeof(NODE) );
	    		m->exp=i;
	    		m->coef=zhengshu[i];
	    		r->next=m;
	    		r=m;
			 }
		 } 
		 r->next=NULL;
	    
		}
		if(fu==0){
			NODE *r=head3;
			for(int i=0;i<=max;i++){
		 	if(zhengshu[i]!=0){
		 		NODE *m;
	    		m = ( NODE * ) malloc( sizeof(NODE) );
	    		m->exp=i;
	    		m->coef=zhengshu[i];
	    		r->next=m;
	    		r=m;
			 }
		 } 
		 r->next=NULL;
		}

		
	
}
  
/* PRESET CODE END - NEVER TOUCH CODE ABOVE */  

 

然而还是过不了

两个WA,两个RE

考虑了00输出之后,就两个RE了

把10010改为102399后就最后一个RE了

所以题目的意思是让我们的到系数了就直接建表

void multiplication(NODE *head1, NODE *head2, NODE *head3)
{

    NODE *p, *q, *r;
    p = q = r = head3;
    NODE *h1 = head1->next, *h2 = head2->next;
    int coef = 0, exp = 0;
    

    while(h1 != NULL)
    {
        while(h2 != NULL)
        {
            coef = h1->coef * h2->coef;
            if (coef == 0)
            {
                h2 = h2->next;
                continue;
            }

            exp = h1->exp + h2->exp;

            if (p->next == NULL)
            {
                NODE *s = (NODE*)malloc(sizeof(NODE));
                s->coef = coef;
                s->exp = exp;
                s->next = NULL;

                p->next = s;
            }
            else
            {
               
                if(r->next != NULL && exp > r->next->exp)
                {
                    q = r;

                    while(q->next != NULL && exp > q->next->exp)
                    {
                        q = q->next;
                        r = q;
                    }
                }
                else
                {
                    while(q->next != NULL && exp > q->next->exp)
                    {
                        q = q->next;
                        r = q;
                    }
                }

                NODE *temp = q->next;
                if(q->next == NULL)
                {
                    NODE *s = (NODE*)malloc(sizeof(NODE));
                    s->coef = coef;
                    s->exp = exp;
                    s->next = NULL;

                    q->next = s;
                }
                else if(temp->exp == exp)
                {
                    temp->coef += coef;
                    if(temp->coef == 0)
                    {
                        NODE *dele = temp->next;
                        q->next = dele;
                        free(temp);
                    }
                }
                else if(temp->exp > exp)
                {
                    NODE *s = (NODE*)malloc(sizeof(NODE));
                    s->coef = coef;
                    s->exp = exp;

                    q->next = s;
                    s->next = temp;
                }
            }
            
            h2 = h2->next;
            q = head3;
        }
        
        h2 = head2->next;
        h1 = h1->next;
    }

    
    if(head3->next == NULL)
    {
        NODE *s = (NODE*)malloc(sizeof(NODE));
        s->coef = 0;
        s->exp = 0;
        s->next = NULL;

        head3->next = s;
    }
    return;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值