【数据结构03】lab1多项式乘法

实验题目

多项式乘法问题

实验目的

设计一个一元稀疏多项式简单计算器

实验内容与要求

一元稀疏多项式简单计算器的基本功能是:
(1)输入并建立多项式;
(2)输出多项式,输出形式为整数序列:n,c1,e1,c2,e2,…,cn,en,其中n是多项式的项数,ci和ei分别是第i项的系数和指数,序列按指数降序排列。
(3)多项式a与多项式b相乘,建立多项式。

实验内容和实验步骤

1、实验构思和设计

本次实验是要建立一个多项式乘法,在写程序时,难点在于怎样存储这个多项式以及完成运算。
想到存储多项式,第一想法是用一个链表,这个链表包含系数和次数,但是构造链表容易,用这个链表进行多项式的乘法比较难想。其次是用数组,数组存放的思路是,数组的下标是多项式中某项的次数,数组的内容是该项的系数。
用数组的优点是,在进行乘法的时候,数组的下标可以直接相加,而数组的内容可以直接相乘,最后把结果存放在另一个新数组里。例如2x^2^*3x^3^时,定义num1[2]=2,num2[3]=3,这样相乘的结果就是num3[2+3]=num1[2]*num2[3]

怎样设计输入呢?输入的依次是系数,次数,存放的方式是用一个for循环,循环次数较多,最后说系数输入0结束,在for循环中用break跳出,代码如下

for (i = 0; i < 30; i++)
	{
		cin >> c1;
		if(c1==0) break; 
		cin >> c; 
		num[c] = c1;
	}

输入端就可以写

cout << "请输入多项式,输入格式依次为系数,次数,最后输入0结束" << endl;

还剩最后一个输出结果,一开始是写成这样的

for(int i=1; i<30; i++)
{
	if(num3[i])
	{
		cout << num3[i] << "x^" << i <<  "+";
	}
}

但是这段程序有一个很明显的问题,就是式子最后面会跟一个 + ,如何把后面的+去掉呢?
把代码更改为

int temp = 0;
for(int i=29; i>=0; i--)
{
	if(num3[i] != 0)
	{
        if(temp && num3[i] > 0) {cout << "+";}
        else if(num3[i] < 0) {cout << "-";}
        if(num3[i]!=1)
		printf("%d",(num3[i] > 0) ? num3[i]: -num3[i]);
		cout << "x^" << i;
		temp++;
	}
}

成功解决,并且省略了系数为1的时候出现的那个“1”,同时考虑了1、输出要降序 2、系数为负数时怎样确定+ -符号,更符合数学逻辑

另外在相乘的时候,我一开始写的是

for (int i = 0; i <= 30; i++)//遍历一个乘数
	{
		if (num1[i] == 0) continue;
		for (int j = 0; j <= 30; j++)//遍历第二个乘数
		{
			if (num2[j] == 0) continue;
			num3[i + j] = num1[i] * num2[j];
		}
	}

但是调试发现,结果并不是正确的,调试了很久都没有想到问题出在哪里,最后才想到,问题就出在num3[i + j] = num1[i] * num2[j];这一行,原因是如果相乘之后,应该把次数相等的项相加,但是这一行的意思是把重复出现的次数相等的项替换掉,加上一个+,即改成num3[i + j] += num1[i] * num2[j];问题就解决了

当把所有代码写完后调试发现,忘了考虑了一个很重要的事情,次数也是有负数的,但是我把次数作为了数组的下标,数组下标是不能有负数了,我这里参考使用移码形式,把代码更改后解决了这个问题

2、最终结果

#include<iostream>
using namespace std;

void init(int* num)
{
	int c, c1;
	cout << "请输入多项式,输入格式依次为系数,次数,最后输入0结束" << endl;
	for (int i = 0; i < 20; i++)
	{
		cin >> c1;
		if (c1 == 0) break;
		cin >> c;
		num[c + 500] += c1;
	}
}

void mu(int* num1, int* num2, int* num3)//多项式乘法
{
	for (int i = 0; i <= 1000; i++)//遍历一个乘数
	{
		if (num1[i] == 0) continue;
		for (int j = 0; j <= 1000; j++)
		{
			if (num2[j] == 0) continue;
			num3[i + j - 500] += num1[i] * num2[j];//num3[i + j] = num1[i] * num2[j];
		}
	}
	cout << "\n输出的结果为" << endl;
	int temp = 0;
	for (int i = 999; i >= 0; i--)
	{
		if (num3[i] != 0)
		{
			if (temp && num3[i] > 0) { cout << "+"; }
			else if (num3[i] < 0) { cout << "-"; }
			if (num3[i] != 1)
				printf("%d", (num3[i] > 0) ? num3[i] : -num3[i]);
			cout << "x^" << i - 500;
			temp++;
		}
	}
}


int main()
{
	int num[1000] = { 0 }, num2[1000] = { 0 }, num3[1000] = { 0 };
	init(num);
	init(num2);
	mu(num, num2, num3);
	return 0;
}

3、时空分析

由于最多是两层循环,循环的次数都是常数,故复杂度为O(1)

4、输入值的范围

输入的多项式最多为20项,系数为任意值,最后输出的多项式的次数在±500之间

5、实验用测试数据和相关结果分析

实验数据依次为(依次为系数,次数)

实验次数第一个多项式第二个多项式
11 2 3 41 2 3 4
2-1 46 3
33 4 8 42 2 2 2 2 0
4-2 2 6 83 -5 8 9 5 -4

第一个是正常测试,第二个是系数为负数,第三个为有可以合并的项,且指数为0,看是否与结束的0混淆,第四个是指数带负数,经测试全部通过,测试结果如下:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值