PTA 7-2 一元多项式的乘法与加法运算 (C语言实现)

题目网址:https://pintia.cn/problem-sets/15/problems/710
题目描述:设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。

输入样例:
4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1
输出样例:
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

题目分析:这道题的关键不是算法,而是用来存储系数和指数的数据结构的选择。通常我们的第一反应是用数组,数组的第i个元素存储 x^i 这一项的系数,但是一旦遇到多项式乘法后,数组将会变成一个稀疏矩阵,加上项数的不确定性,可能会导致存储空间的不足,因此数组是很坏的一个选择。那么既具有灵活存储又能动态分配内存空间的ADT非链表莫属了。
算法解析:由于题目要求按照指数降序输出,因此为了方便链表元素前后搜索或置换,我采用了双向链表。

  1. 多项式加法:按照归并排序中归并的方法,定义一个头结点名为sum的链表存储加法结果,每次取两个多项式头部的元素进行比较,小的先进入sum链表,若相等则系数相加后进入链表。进入链表的元素所在的节点指针指向下一个直至NULL
  2. 多项式乘法:定义一个头结点名为mul的链表存储乘法结果。乘法的难点在于不能向加法那样顺序增添节点,这时每个节点的last和next指针就有用了。采用最笨拙的暴力搜索,使两个多项式一项一项分别相乘,将所乘得到的结果与mul尾结点比较,若尾结点指数大,则添加至新尾结点,若尾结点指数小,则用一个新的循环向前搜索,直至找到正确的位置,插入,若与尾结点指数相同,则系数相加即可。同时要注意各链表指针的变化。
  3. 输出:考虑到存在零多项式(项数为0或结果系数为0的情况),我统一在输出函数进行处理

AC代码:我的算法可能有些笨拙,如果有更好的算法,还请大佬们留言告知,谢谢

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

struct Node{
	struct Node* last;
	int cof;
	int exp;
	struct Node* next;
};
int m,n;

struct Node* Creat(int k);
struct Node* Print(struct Node* head);
struct Node* Sum(struct Node* head1, struct Node *head2);
struct Node* Mul(struct Node* head1, struct Node *head2);

int main()
{
	struct Node* head1, *head2;
	struct Node* sum, *mul;
	
	scanf("%d",&m);
	if (m!=0)
	{
		head1 = Creat(m);
	}
	else
	{
		head1 = (struct Node*)malloc(sizeof(struct Node));
		head1->cof = head1->exp = 0;
		head1->last = head1->next = NULL;
	}
	scanf("%d",&n);
	if (n!=0)
	{
		head2 = Creat(n);
	}
	else
	{
		head2 = (struct Node*)malloc(sizeof(struct Node));
		head2->cof = head2->exp = 0;
		head2->last = head2->next = NULL;
	}
	
	sum = Sum(head1, head2);
	mul = Mul(head1, head2);
	
	Print(mul);
	printf("\n");
	Print(sum);
} 

struct Node* Creat(int k)
{
	struct Node* head, *tail, *p;
	int i;
	for (i=0; i<k; i++)
	{
		p = (struct Node*)malloc(sizeof(struct Node));
		scanf("%d %d",&p->cof, &p->exp);
		if (i==0)
		{
			head = tail = p;
			tail->next = NULL;
			head->last = NULL;
		}
		else
		{
			tail->next = p;
			p->last = tail;
			tail = p;
			p->next = NULL;
		}
	}
	return head;
}

struct Node* Print(struct Node* head) //同时处理零多项式的情况
{
	int count = 0;
	if (head==NULL)
	{
		printf("0 0");
		return NULL;
	}
	while (head!=NULL)
	{
		if (head->cof==0) 
		{
			head = head->next;
			continue;
		}
		if (count==0)
		{
			printf("%d %d",head->cof,head->exp);
			count = 1;
		}
		else
		{
			printf(" %d %d",head->cof, head->exp);
		}
		head = head->next;
	}
	if (count==0) printf("0 0");
}

struct Node* Sum(struct Node* head1, struct Node *head2)
{
	struct Node*sum = NULL, *head = NULL, *tail = NULL;
	while (head1!=NULL && head2!=NULL)
	{
		sum = (struct Node*)malloc (sizeof(struct Node));
		if (head==NULL)
		{
			head = tail = sum;
			head->last = NULL;
			tail->next = NULL;
		}
		else
		{
			tail->next = sum;
			sum->last = tail;
			tail = sum;
			tail->next = NULL;
		}
		if (head1->exp==head2->exp)
		{
			sum->cof = head1->cof + head2->cof;
			sum->exp = head1->exp;
			head1 = head1->next;
			head2 = head2->next; 
		}
		else if(head1->exp > head2->exp)
		{
			sum->cof = head1->cof;
			sum->exp = head1->exp;
			head1 = head1->next;
		}
		else
		{
			sum->cof = head2->cof;
			sum->exp = head2->exp;
			head2 = head2->next;
		}
	}
	while (head1!=NULL)
	{
		sum = (struct Node*)malloc(sizeof(struct Node));
		tail->next = sum;
		sum->last = tail;
		tail = sum;
		tail->next = NULL;
		sum->cof = head1->cof;
		sum->exp = head1->exp;
		head1 = head1->next;
	}
	while (head2!=NULL)
	{
		sum = (struct Node*)malloc(sizeof(struct Node));
		tail->next = sum;
		sum->last = tail;
		tail = sum;
		tail->next = NULL;
		sum->cof = head2->cof;
		sum->exp = head2->exp;
		head2 = head2->next;
	}
	return head;
}

struct Node* Mul(struct Node* head1, struct Node *head2)
{
	struct Node* mul = NULL, *head = NULL, *tail = NULL, *find = NULL, *insert = NULL;
	struct Node* newhead = NULL;
	if (m==0||n==0)
	{
		return NULL;
	}
	while (head1!=NULL)
	{
		newhead = head2;//防止丢失原链表头结点
		while (newhead!=NULL)
		{
			mul = (struct Node*)malloc(sizeof(struct Node));
			if (head==NULL)
			{
				head = tail = mul;
				head->last = NULL;
				tail->next = NULL;
			}
			
			mul->cof = head1->cof * newhead->cof;
			mul->exp = head1->exp + newhead->exp;
			if (mul->exp < tail->exp)//如果所得结果小于mul的尾结点指数,则增添为新的尾结点
			{
				tail->next = mul;
				mul->last = tail;
				tail = mul;
				tail->next = NULL;
			}
			else 
			{
				find = tail;
				while (find->last!=NULL && mul->exp > find->exp)//想前搜索至正确位置
					find = find->last;
					if (mul->exp < find->exp)
					{
						insert = (struct Node*)malloc(sizeof(struct Node));
						insert->cof = mul->cof;
						insert->exp = mul->exp;
					
						//inserting
						find->next->last = insert;
						insert->last = find;
						insert->next = find->next;
						find->next = insert;
					
						mul = NULL;
					}
					else //mul->exp==find->exp
					{
						if (find->last!=NULL)
						find->cof += mul->cof;
						mul = NULL;
					}
			}
			newhead = newhead->next;
		}
		head1 = head1->next;
	}
	return head;
}
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 一元多项式乘法运算是指将两个或多个一元多项式相乘的运算。例如,将多项式f(x)=3x^2+2x+1和g(x)=4x^3+5x^2+6x+7相乘,得到的结果为: f(x)×g(x) = (3x^2+2x+1)×(4x^3+5x^2+6x+7) = 12x^5+23x^4+32x^3+31x^2+18x+7 一元多项式加法运算是指将两个或多个一元多项式相加的运算。例如,将多项式f(x)=3x^2+2x+1和g(x)=4x^3+5x^2+6x+7相加,得到的结果为: f(x)+g(x) = (3x^2+2x+1)+(4x^3+5x^2+6x+7) = 4x^3+8x^2+8x+8 在一元多项式乘法加法运算中,需要注意多项式的次数和系数的运算。同时,还需要注意运算的顺序和规律,以避免出现错误。 ### 回答2: 一元多项式乘法运算是指将两个多项式相乘得到一个新的多项式。例如,(3x + 2)(4x + 5)可以通过分配律展开得到12x^2 + 23x + 10。在进行乘法运算时,我们需要将每个多项式中的每一项相乘,然后将结果相加。 与乘法不同,一元多项式加法运算比较简单,只需要将相同次数的项的系数相加即可。例如,(2x^2 + 3x + 4) + (5x^2 + 2x + 1) = 7x^2 + 5x + 5。如果两个多项式中存在相同次数的项,我们只需要将它们的系数相加,然后将结果写在相同次数的项下面。 在进行一元多项式乘法加法运算时,我们需要注意多项式的次数。对于一个多项式P(x),它的次数指的是其中最高阶项的次数。例如,对于P(x) = 2x^3 + 3x^2 + 4x + 1,其次数为3,因为最高阶项是2x^3。 那么,怎样进行一元多项式乘法加法运算呢?下面给出具体的计算方法: 1. 一元多项式乘法运算 对于两个多项式P(x)和Q(x),它们的乘积可以表示为: P(x)Q(x) = (a_nx^n + a_{n-1}x^{n-1} + ... + a_1x + a_0) × (b_mx^m + b_{m-1}x^{m-1} + ... + b_1x + b_0) 其中,a和b分别表示两个多项式中各项的系数,n和m分别表示它们的次数。 我们可以使用分配律将每一个项相乘,然后将所有的结果相加。例如,对于P(x) = 3x^2 + 2x + 1和Q(x) = 4x + 5,它们的乘积可以表示为: P(x)Q(x) = (3x^2 + 2x + 1) × (4x + 5) = 12x^3 + 15x^2 + 8x^2 + 10x + 4x + 5 = 12x^3 + 23x^2 + 14x + 5 在进行乘法运算时,我们需要按照降幂的顺序从高到低依次计算每一项。例如,在计算12x^3时,我们需要将P(x)和Q(x)中次数为3的项相乘,即3x^2 × 4x,然后将结果12x^3写在新多项式中次数为3的项下面。 2. 一元多项式加法运算 对于两个多项式P(x)和Q(x),它们的和可以表示为: P(x) + Q(x) = (a_nx^n + a_{n-1}x^{n-1} + ... + a_1x + a_0) + (b_mx^m + b_{m-1}x^{m-1} + ... + b_1x + b_0) 其中,a和b分别表示两个多项式中各项的系数,n和m分别表示它们的次数。 我们只需要将相同次数的项的系数相加即可。例如,对于P(x) = 2x^2 + 3x + 4和Q(x) = 5x^2 + 2x + 1,它们的和可以表示为: P(x) + Q(x) = (2x^2 + 3x + 4) + (5x^2 + 2x + 1) = 7x^2 + 5x + 5 在进行加法运算时,我们需要将P(x)和Q(x)中相同次数的项的系数相加,然后将结果写在新多项式中相同次数的项下面。如果两个多项式中不存在相同次数的项,我们可以直接将它们写在新的多项式中。 ### 回答3: 一元多项式乘法运算指的是两个多项式相乘得到一个新的多项式。一元多项式乘法运算可以通过拆分展开的方式进行,具体方法为将每个多项式的各项相乘,再将所有相乘得到的项进行合并。例如,设有两个一元多项式f(x)和g(x) f(x) = a0 + a1x + a2x^2 + …… + anx^n g(x) = b0 + b1x + b2x^2 + …… + bmx^m 则f(x)和g(x)的乘积fg(x)为 fg(x) = (a0b0) + (a0b1 + a1b0)x + (a0b2 + a1b1 + a2b0)x^2 + …… + (anbm)x^n+m 其中,aibj表示f(x)和g(x)中第i+1项和第j+1项的系数的乘积。可以看出,fg(x)的次数为f(x)和g(x)的次数之和。 与乘法不同,一元多项式加法运算是将两个多项式相加得到一个新的多项式。具体方法为将f(x)和g(x)中同一次项的系数相加,然后将所有相加得到的项进行合并。例如,设有两个一元多项式f(x)和g(x) f(x) = a0 + a1x + a2x^2 + …… + anx^n g(x) = b0 + b1x + b2x^2 + …… + bmx^m 则f(x)和g(x)的和f+g(x)为 f+g(x) = (a0+b0) + (a1+b1)x + (a2+b2)x^2 + …… + (an+bm)x^max{n,m} 其中,max{n,m}表示n和m中的最大值。可以看出,f+g(x)中的次数不超过max{n,m}。 一元多项式乘法加法运算在代数学中有广泛的应用。在多项式的乘法运算中,还存在着多项式的因式分解和求根等问题,是数学中的重要研究领域。在实际应用中,多项式的乘法和加法也常用于信号处理、计算机科学等领域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值