<数据结构学习>一元多项式的相乘

目录

题目描述

题目:

前置代码:

问题分析

头部代码:

main函数:

子函数:

1、建立多项式链表的函数

2、输出函数:

解题方法

一元多项式的乘法:

一元多项式的加法

总结


这篇文章是我开始系统学习算法时为记录学习过程写的,比较适合小白,大佬请跳过。不当之处请大家批评指正。

题目描述

题目:

采用链表形式,求两个一元多项式的乘积:h3 = h1*h2。函数原型为:void multiplication( NODE * h1, NODE * h2, NODE * h3 )。

输入:

输入数据为两行,分别表示两个一元多项式。每个一元多项式以指数递增的顺序输入多项式各项的系数(整数)、指数(整数)。

例如:1+2x+x2表示为:<1,0>,<2,1>,<1,2>,

输出:

以指数递增的顺序输出乘积: <系数,指数>,<系数,指数>,<系数,指数>,

零多项式的输出格式为:<0,0>,

前置代码:

#include <stdio.h>  
#include <stdlib.h>  
  
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;  
}  

问题分析

分析前置代码:

头部代码:

#include <stdio.h>  
#include <stdlib.h>  
  
typedef struct node  //定义结构体
{   int  coef, exp;  //定义整型系数和指数
    struct node  *next;   //指向下一个结构体的指针
} NODE;  

main函数:

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;  
}  

子函数:

1、建立多项式链表的函数

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 =='-' )  //遇到符号的时候系数要乘-1
             sign = -1;  
        else if( c >='0'&& c <='9' )  //系数不一定是一位数,有可能是多位,注意乘10
        {    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;  //重置标志量
        }  
    }  
}  

2、输出函数:

void output( NODE * head )   //输出多项式的各项
{  
    while ( head->next != NULL )  
    {   head = head->next;  //移动头指针
        printf("<%d,%d>,", head->coef, head->exp );   //输出各项
    }  
    printf("\n");  
}  

解题方法

一元多项式的乘法:

我们需要编写的是多项式1和多项式2相乘之后的结果,并将其赋到多项式3中。

由多项式乘法的计算规律,我们可以想到,多项式1和多项式2的每一项都要两两相乘一次。

其中有一些项的指数可能会重复。我们需要把指数相同的项的系数合并。然后还要注意按指数由小到大的顺序排列各项。

有了这个思路,我们可以设计如下代码:

void multiplication( NODE *head1, NODE *head2 , NODE *head3 )
{
	int ind,k,flag=0;
	NODE *p,*q,*r,*t,*m,*ss,*tem;
	p=(NODE*)malloc(sizeof(NODE));
	q=(NODE*)malloc(sizeof(NODE));
	r=(NODE*)malloc(sizeof(NODE));
	t=(NODE*)malloc(sizeof(NODE));
	tem=(NODE*)malloc(sizeof(NODE));
	p=head1;  //p为多项式1的移动指针,最开始指向多项式1头部
	q=head2;  //q为多项式2的移动指针,最开始指向多项式2头部
	r=head3->next;  //r为多项式3的移动指针,最开始指向多项式3的第一个元素
	t=head3;  //t为多项式3的移动指针,最开始指向多项式3的头部

	tem=head3->next;   //tem为多项式3的移动指针,用来记录上一轮乘出来的元素
                        //放到多项式3的哪个位置了,如果这次的指数大于上次该位置的指数,
                          //直接从该位置往后找,节省时间

	while(p->next!=NULL) //当p的下一个不为空时,往后遍历
	{
		p=p->next;  
		q=head2; //每次大层循环(多项式1)更新一项时,多项式2都从第一项开始遍历
		tem=head3->next;  //tem初始化
		while(q->next!=NULL)  //当q的下一个不为空时,往后遍历
		{
			q=q->next;
			k=(p->coef)*(q->coef);  //计算当前两项相乘的系数
			ind=(p->exp)+(q->exp);  //计算当前两项相乘的指数
			if(k==0)   //如果系数为0,直接跳过该轮
			{
				continue;
			}
			m=(NODE*)malloc(sizeof(NODE));  //否则,建立一个结构体变量存储该项
			m->coef=k;
			m->exp=ind;
			if(r!=NULL) //当多项式3中有元素时
			{
				if(tem!=NULL&&(m->exp)>(tem->exp))  
				{
					t=tem;   //看一下上一轮tem所指元素的指数是否小于该轮元素的指数
					r=t->next; //如果是,那么直接让r从tem后开始遍历,找到
                                  //多项式3中合适的插入位置,节省时间!!
				}
			}
				while(r!=NULL)  //如果上一轮tem所指元素的指数大于该轮元素的指数,则没法省时
				{                      //r从第一个元素开始遍历
					if(r->exp==ind) //如果该元素指数和多项式3中某项指数相等,则将该元素系数
					{                       //加到多项式3中这项系数上
						r->coef+=k;
						if(r->coef==0)   //判断一下加完后的系数是否为0,若为0,则在
						{                   //多项式3中删除该项
							t->next=r->next; 
							r=t->next;
						}
						r=head3->next;  //重置r指针和t指针
						t=head3;
						flag=1;  //设置标志量,证明已经处理完该新元素
						break;  //立刻退出
					}
					else if(r->exp<ind)   //若该元素指数小于多项式3中某项指数,则往后遍历
					{
						r=r->next;   //后移r指针和t指针
						t=t->next;
						tem=t;   //tem和t指针看齐
					}
					else if(r->exp>ind)  //若该元素指数大于多项式3中某项指数
					{                     //说明该元素项要插到r指针前t指针后
						m->next=r;
						t->next=m;
						r=head3->next;   //插入后重置r指针和t指针
						t=head3;
						flag=1;   //设置标志量,证明已经处理完该新元素
						break;   //立刻退出
					}
				}
				if(flag==0)  //如果标志量未变化,说明该元素项的指数大于了多项式3中所有项的指数
				{              //此时要将该元素项插到多项式3的最后
					m->next=r;
					t->next=m;
					tem=t;
					r=head3->next;  //加入后重置r指针和t指针
					t=head3;
				}
				flag=0;   //标志项重置
		}
	}
	if(head3->next==NULL)   //如果最后多项式3中一项也没有(说明系数全为0,都被删除了)
	{
		ss=(NODE*)malloc(sizeof(NODE));   //此时需要将<0,0>放入多项式3中
		head3->next=ss;
		ss->next=NULL;
		ss->coef=0;
		ss->exp=0;
	}
}

一元多项式的加法

拓展一下一元多项式的加法:

 伪代码:

建立多项式1的移动指针p;  置于多项式1头部。

建立多项式2的移动指针q;  置于多项式2头部。

当p->next不为空时

{

        p=p->next;

       如果q->next不为空
        {

                q=q->next;

                比较p->next->exp和q->next->exp

                如果相等,就把q->next->coef加到p->next->coef上

                如果小于,就后移p

                如果大于,就把q插到p前面

        }

}

检查操作后的多项式1,把系数为0的项删掉

检查删完后的多项式1,若为空,加入<0,0>

返回多项式1头指针

总结

解决多项式乘法问题时我们需要注意,插入每一项的位置都要使多项式3满足指数从小到大排列。

为了不超时,我们还设置了一个tem指针记录上一轮插入多项式3的元素的位置,如果下一轮要插入的元素的指数大于tem所指元素的指数,则直接让r从tem的下一个元素开始遍历即可。

对于加法来说,只需要把其中一个多项式看做基体,合并即可,不需要另建一个多项式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值