链表应用一元多项式
说明
一元多项式 A ( x ) = a 1 x e 1 + a 2 x e 2 + a 3 x e 3 + a 4 x e 4 + ⋯ 一元多项式\\ A(x)=a_1 x^{e_1} +a_2 x^{e_2}+a_3 x^{e_3}+a_4 x^{e_4}+⋯ 一元多项式A(x)=a1xe1+a2xe2+a3xe3+a4xe4+⋯
可以用链表存储,每个结点保存的信息为每个项的系数和指数
多项式的项
项的定义
//多项式的一项(只要数据部分)
class term
{
public:
double coefficient;//系数
int exponent;//指数
}
项的相关功能
构造、输出、两项相加、两项相乘
比较两项指数大小(后面多项式加法用)
class term
{
//省略一些代码……
public:
//重载“输出号”<<,以输出一项
friend ostream& operator<<(ostream &out,term a);
//构造函数
term(double c=0, int e=0);
/*功能:重载加号,实现两个项的相加
* 输入:
* a 另一个项
* 返回:
* 结果项,如果指数项不同则什么也不做
* 其它:
* 这只是多项式的一项,所以相加要求指数相同,如果指数不同则什么也不做,直接返回0,0
*/
term operator+(term a);
/*功能:重载乘号,实现两个项的相乘
* 返回:新的项
* 其它:比如2x * 3x^2 = 6x^3
*/
term operator*(term a);
};
//比较结果
enum cmp_result
{
less = -1,//小于
equal = 0,//等于
greater = 1//大于
};
/* 功能:比较两个项
* 输入:
* t1,t2两个项
* 返回:
* 比较结果
* 其它
*/
cmp_result term_cmp(term t1, term t2);
具体实现
term::term(double c, int e)
{
coefficient = c;
exponent = e;
}
ostream& operator<<(ostream& out, term a)
{
//正常的多项式若有常数项,必然是第一个
//若指数等于0,即常数项,一般只打印系数
if (a.exponent == 0)
out << a.coefficient;
else
{
//若系数等于1,一般不再打印该系数,只打印“+”
if (a.coefficient != 1)
{
out << showpos << a.coefficient;
}
else
out << '+';
out << 'x';
//若指数等于1,一般不再打印该指数
if (a.exponent != 1)
out << '^' <<noshowpos<< a.exponent;
}
out << ' ';
return out;
}
term term::operator+(term a)
{
term t(0, 0);
if (this->exponent == a.exponent)//只有系数相等才加,系数不等什么也不做
{
t.coefficient = this->coefficient + a.coefficient;
t.exponent = this->exponent;
}
return t;
}
term term::operator*(term a)
{
term t;
t.coefficient = this->coefficient * a.coefficient;
t.exponent = this->exponent + a.exponent;
return t;
}
cmp_result term_cmp(term t1, term t2)
{
if (t1.exponent < t2.exponent) return cmp_result::less;
else if (t1.exponent == t2.exponent) return cmp_result::equal;
else return cmp_result::greater;
}
多项式
多项式定义
显然,以各项为数据的链表即为多项式
我这里再简单封装一下
//多项式
class Polynomail
{
private:
list<term> theTermList;//显然,以各项为数据的链表即为多项式
}
这里说明一下为什么使用双向链表list而不是单链表forward_list,按理说使用单链表就行了,不过
其一
模板forward_list插入的相关函数中没有在尾部插入pust_buck,一些时候得和常人逻辑“反过来”
其二
forward_list没有返回容器大小的函数size,使用不便
当然如果不封装,直接
typedef list<term> Polynomail
也不错
多项式相关功能
杂项
输出、构造
class Polynomail
{
//省略一些代码……
//重载<<以输出
friend ostream& operator<<(ostream& out, Polynomail aPolynomail);
public:
/*
* 功能:无参构造,什么也不做
* 输入:
* 返回:无
* 其它:
*/
Polynomail();
/*
* 功能:根据已经存在的项数组,建立一元多项式P
* 输入:
* t:项数组指针
* n:项的个数
* 返回:无
* 其它:
* 要求项数组中,项的指数从小到大排列
*/
Polynomail(term* const t, uint16_t const n);
//省略一些代码……
};
实现
ostream& operator<<(ostream& out, Polynomail aPolynomail)
{
if (!(aPolynomail.theTermList.empty()))
{
uint16_t number = aPolynomail.theTermList.size();
out << "共有" << number << "项" << endl;
list<term>::iterator it = aPolynomail.theTermList.begin();
for (int i = 0; i < number; i++)
{
out << *it;
it++;
}
}
return out;
}
Polynomail::Polynomail()
{
}
Polynomail::Polynomail(term* const t, uint16_t const n)
{
for (int i = 0; i < n; i++)
{
this->theTermList.push_back(t[i]);
}
}
多项式加法
class Polynomail
{
//省略一些代码……
/*功能:重载加号,完成多项式相加运算,即:Pc=Pa+Pb
* 输入:
* Pb:另一个多项式
* 返回:新的多项式,即相加的结果
* 其它:
*/
Polynomail operator+(Polynomail& Pb);
//省略一些代码……
};
实现
Polynomail Polynomail::operator+(Polynomail& Pb)
{
Polynomail Pc;
list<term>::iterator ita = this->theTermList.begin();//自己就是Pa
list<term>::iterator itb = Pb.theTermList.begin();
double sum = 0;
while (ita != this->theTermList.end() && itb != Pb.theTermList.end())
{
switch (term_cmp(*ita, *itb))//比较多项式的指数
{
case cmp_result::less://如果ita的指数比itb的小
Pc.theTermList.push_back(*ita);//插入ita
ita++;
break;
case cmp_result::greater://如果ita的指数比itb的大
Pc.theTermList.push_back(*itb);//插入itb
itb++;
break;
case cmp_result::equal://如果两项指数相等
sum = ita->coefficient + itb->coefficient;//得到新的项的系数
if (sum != 0)//如果系数不为零
{
Pc.theTermList.push_back(term(sum, ita->exponent));//插入新的项
}
//系数相加为0,这一项就没了,不用插入什么
ita++;
itb++;
break;
default:
break;
}
}
//插入Pa中剩余结点
while (ita != this->theTermList.end())
{
Pc.theTermList.push_back(*ita);
ita++;
}
//插入Pb中剩余结点
while (itb != Pb.theTermList.end())
{
Pc.theTermList.push_back(*itb);
itb++;
}
return Pc;
}
我用的教材中的多项式加法,它A(x)+B(x)之后,结果保存在A(x)中,B(x)就没了,感觉很奇怪
我这里的代码就是有一个新的多项式,结果保存在新的C(x)中
多项式乘法
乘法可以分解成一系列的加法运算
M
(
x
)
=
A
(
x
)
∗
B
(
x
)
=
A
(
x
)
∗
[
b
1
x
e
1
+
b
2
x
e
2
+
b
3
x
e
3
+
b
4
x
e
4
+
⋯
]
=
∑
i
=
1
n
A
(
x
)
∗
b
i
x
e
i
M(x)=A(x)*B(x)\\ =A(x)*[b_1 x^{e_1} +b_2 x^{e_2}+b_3 x^{e_3}+b_4 x^{e_4}+⋯]\\ =\sum_{i=1}^n A(x)*b_i x^{e_i}
M(x)=A(x)∗B(x)=A(x)∗[b1xe1+b2xe2+b3xe3+b4xe4+⋯]=i=1∑nA(x)∗bixei
其中每一项都是一个一元多项式
先实现一元多项式和一项相乘
一元多项式和一项相乘定义
class Polynomail
{
//省略一些代码……
/*功能:重载乘号,完成多项式和一项相乘,即:Pb=Pa*t
* 输入:
* t:去乘的项
* 返回:新的多项式,即相乘的结果
* 其它:
*/
Polynomail operator*(term& t);
//省略一些代码……
};
实现一元多项式和一项相乘
//重载乘号实现多项式和一项相乘
Polynomail Polynomail::operator*(term& t)
{
Polynomail tem;
list<term>::iterator it = this->theTermList.begin();
uint16_t num = this->theTermList.size();
for (uint16_t i = 0; i < num; i++)
{
tem.theTermList.push_back((*it) * t);//新的多项式每项为,原多项式各项乘该项
it++;
}
return tem;
}
然后就可以实现多项式乘法了
多项式乘法定义
class Polynomail
{
//省略一些代码……
/*功能:重载乘号,完成两多项式相乘,即:Pc=Pa*Pb
* 输入:
* Pb:另一个多项式
* 返回:新的多项式,即相乘的结果
* 其它:
*/
Polynomail operator*(Polynomail& Pb);
//省略一些代码……
};
多项式乘法实现
//两多项式相乘,即:Pa=Pa*Pb
Polynomail Polynomail::operator*(Polynomail& Pb)
{
Polynomail Pc;//保存最终结果
Polynomail tem;//用来进行多项式和某一项相乘
//link它begin就是第一个存储数据的结点,最多自增Pb.size()-1次,请注意
for (list<term>::iterator itb = Pb.theTermList.begin(); itb!=Pb.theTermList.end(); itb++)
{
tem = (*this) * (*itb);
Pc = Pc + tem;
}
return Pc;
}