如何利用线性表?完成一元多项式运算【内容丰富,简单易懂】
如何利用线性表完成一元多项式运算。多项式每项coef是该项系数,exp是变元x的指数单循环链表、结构体模板、类模板、友元函数以及运算符重载、程序设计思路、项结点实现多项式类、多项式的输入和输出、多项式相加、多项式相乘、重载运算符 将一个多项式看成一个线性表,线性表的元素就是多项式的项。对多项式算术运算而言,连接存储方式更合适。一般来来说,多项式的项数和指数变化较大,难以确定,若采用顺序存储方式,需
🍀🍀🍀🍀🍀🍀本篇干货满满哦~
在学习线性表时遇到了一个有趣的例子:如何用线性表来完成一元多项式的算数实现?
🍀🍀🍀🍀 🍀🍀
多项式我们知道,每项形式均为\[ coef \cdot x ^{exp}, \]coef是该项系数,exp是变元x的指数
🍎本篇程序所包含到的内容:单循环链表、结构体模板、类模板、友元函数以及运算符重载
这里先给大家放几张程序实现的截图
1、多项式的输入与输出
2、多项式的加法运算
3、多项式的乘法运算
具体程序实现👇
目录
🍎程序设计思路
🍎项结点实现
🍎多项式类
🍎多项式的输入和输出
🍎多项式相加
🍎多项式相乘
🍎重载运算符
末尾📖
源码
-
程序设计思路
将一个多项式看成一个线性表,线性表的元素就是多项式的项。对多项式算术运算而言,连接存储方式更合适。一般来来说,多项式的项数和指数变化较大,难以确定,若采用顺序存储方式,需要先分配足够空间,容易造成空间浪费;而采取链接存储方式,动态创建新结点以存储多项式的项,就十分灵活。
-
项结点实现
设每个项结点Term有三个域:系数(coef)、指数(exp)和指向后继结点的指针(link),由此类节点构造带表头结点的单循环链表,存储一个多项式。
Term类包含三个数据成员coef、exp和link,两个构造函数以及如下定义的成员函数
Term* InsertAfter(T c, int e);
- Term* InsertAfter(T c, int e);
- 后置条件:构造一个新项结点 < c , e >,并插在前结点及其后继之间,函数返回新项结点地址。
template <typename T>
struct Term {
Term(int e) :exp(e),coef(0) { this->link = NULL; }
Term(T c, int e, Term* next) :coef(c), exp(e) { this->link = next; }
Term* InsertAfter(T c, int e);
T coef; //系数
int exp; //指数
Term* link; //下一项
};
template< typename T>
Term<T>* Term<T>::InsertAfter(T c, int e) {
link = new Term(c, e, link);
return link;
}
-
多项式类
多项式类Polynominal只有一个数据成员theList,它是指向单循环链表的表头结点的指针,函数成员包括构造函数和析构函数,AddTerms、Output、PolyAdd和PolyMul函数,以及重载 “<<” “>>” “=” 运算符。
- 构造函数建立只有一个表头结点,其coef值域为0,exp值域为-1,link值域为指向自身,形成只有表头结点空单循环链表(可参考上图单循环链表)。析构函数调用Clear函数,释放一个多项式链表中的全部结点,再将表头收回;
- AddTerms函数通过输入流in,输入多项式各项,构造一个多项式;
- Output函数将多项式送输出流;
- 重载 “<<” 和 “>>” 运算符函数是Polynominal的友元函数,它们的功能分别于AddTerms和Output函数相同,只是为了简化程序书写形式而设计;
- PolyAdd函数将多项式 p( x ) 和 q ( x )相加,结果为多项式 *this;
- PolyMul函数将多项式 p( x ) 和 q ( x )相乘,结果为多项式 *this;
template<typename T>
class Polynominal {
public:
Polynominal();
~Polynominal();
void AddTerms(istream& in); //输入多项式
void Output(ostream& out)const; //输出多项式
Polynominal& PolyAdd(const Polynominal& x, const Polynominal& y); //多项式加法
Polynominal& PolyMul(const Polynominal& x, const Polynominal& y); //多项式相乘
void operator=(const Polynominal&x); //重载“=”运算符
void Clear();
private:
Term<T>* theList;
friend ostream& operator<<(ostream&, const Polynominal);
friend ostream& operator>>(ostream&, Polynominal);
};
template<typename T>
Polynominal<T>::Polynominal() {
theList = new Term<T>(-1);
theList->link = theList;
}
template<typename T>
Polynominal<T>::~Polynominal() {
Clear();
delete theList;
}
template<typename T>
void Polynominal<T>::Clear() {
Term<T>* q = theList, * r;
for (r = q->link; r != theList; r = q->link) {
q->link = r->link;
delete r;
}
}
-
多项式的输入和输出
使用AddTerms函数,可以根据需要,从输入流in向一个空多项式添加各项,构成一个多项式(注意,为了简化算法,算法中未包含将用户输入多项式按降幂数据存储的代码) 。
使用Output函数将多项式送输出流,从而输出一个多项式。多项式\[3x^{14}+6x^{2}+2 \]以下列形式输出:3x^14+6x^2+2。
- AddTerms函数从输入流逐个输入多项式的项(系数c和指数e),以输入负指数作为多项式的结束条件。AddTerms函数调用Term类的成员函数InsertAfter(c , e) 构造一个新项结顶,并将其添加到但虚幻链表尾部。初始时,指针q指向空单循环链表的表头结点,新项结顶将插在q指示的结点之后。InsertAfter函数返回新项结点的地址,该地址值被赋给指针q,因此,指针q始终指向尾结点。
- Output函数调用在Term类上重载的 “<<” 运算符。如果高次幂是整系数,则按多项式书写的习惯不打印 “ + ” ;否则,对于非高次幂项,当系数为正时,系数前需另加 “ + ” 号。
template< typename T>
void Polynominal<T>::AddTerms(istream& in) {
Term<T>* q = theList;
T c;
int e;
cout << "输入多项式系数与指数(coef,exp),指数为负数时停止输入\n" << endl;
for (;;) {
cin >> c >> e;
if (e < 0) //如果e为负值,输入完毕
break;
q = q->InsertAfter(c, e);
}
}
template<typename T>
void Polynominal<T>::Output(ostream& out)const {
bool start = true;
Term<T>* p = theList->link;
for (; p != theList; p=p->link) {
if (!start && p->coef > 0)
out << '+';
start = false;
out << *p; //调用Term类上重载的 “<<” 运算符
}
out << endl;
}
//Term类上重载 “<<” 运算符
template <typename T>
ostream& operator<<(ostream& out, const Term<T>& val) {
if (val.coef == 0)
return out;
switch (val.exp) {
case 0:
out << val.coef;
break;
case 1:
if (val.coef != 1)
out << val.coef;
out << "X";
break;
default:
if (val.coef != 1)
out << val.coef;
out << "X^"<<val.exp;
break;
}
return out;
}
-
多项式相加
一元系数多项式相加的例子如图,图中d(x) = a(x) + b(x) ,均为多项式
PolyAdd函数实现一元多项式 x 于 y 的相加,当前多项式对象 *this 是两者之和,该函数返回和多项式。三个多项式都用带头结点的单循环链表表示。初始时,应清空 *this 多项式。
指针p和q分别指向多项式x和y的当前正在进行比较的项。初始时,它们分别指向多项式的第一项,指针t指向多项式 *this 的表头结点。PolyAdd函数调用ExpComp函数事项两项达到指数间的比较。
现将p指示的项的指数 p->exp 于q指示的项的指数 q->exp进行比较,有三种可能的结果,每种结果都需要调用InsertAfter函数,在多项式 *this 的末尾添加新项的结点,并且指针t始终指向多项式 *this 的尾部。三种可能的比较结果如下。
- 若 p -> exp == q -> exp,则合并同类项目=。如果此时 q -> coef + p ->coef != 0,则在多项式 *this 的最后添加新项结点,其系数为q -> coef + p ->coef ,指数为 p -> exp,指针p和q均后移一项。
- 若 p -> exp > q -> exp,则在多项式 *this 的最后添加新项结点,其系数为 p ->coef ,指数为 p -> exp,指针p后移一项。
- 若 p -> exp < q -> exp,则在多项式 *this 的最后添加新项结点,其系数为 q ->coef ,指数为 q -> exp,指针q后移一项。
int ExpComp(int x, int y) {
if (x == y)
return 0;
else if (x > y)
return 1;
else
return -1;
}
template<typename T>
Polynominal<T>& Polynominal<T>::PolyAdd(const Polynominal<T>& x, const Polynominal<T>& y) {
Clear();
Term<T>* t = theList, * p = x.theList->link, * q = y.theList->link;
while (p->exp >= 0 || q->exp >= 0) {
switch (ExpComp(p->exp, q->exp)) {
case -1:
t->InsertAfter(q->coef, q->exp);
q = q->link;
break;
case 0:
if (p->coef + q->coef != 0)
t = t->InsertAfter(p->coef + q->coef, p->exp);
p = p->link;
q = q->link;
break;
case 1:
t->InsertAfter(p->coef, p->exp);
p = p->link;
break;
}
}
return *this;
}
-
多项式相乘
大家早已熟知,乘法可以通过加法来实现。事实上,只需将被乘数多项式分别于乘数多项式的每项相乘,然后将所得的多项式相加,就可求两个多项式的乘积。例如,
template<typename T>
Polynominal<T>& Polynominal<T>::PolyMul(const Polynominal& x, const Polynominal& y) {
Clear();
Polynominal<T> s, t;
Term<T>* q, * p = y.theList->link;
for (; p != y.theList; p = p->link) {
s = x;
for (q = s.theList->link; q != s.theList; q = q->link) {
q->coef = p->coef * q->coef;
q->exp = p->exp + q->exp;
}
t = PolyAdd(s, t);
}
return *this;
}
-
重载运算符
重载 赋值(=) 和输出(>>) 输出(<<)运算符。重载这几个运算符可以简化程序。重载赋值运算符为了防止浅拷贝问题。
template<typename T>
ostream& operator<<(ostream& out, const Polynominal<T>& x) {
x.Output(out);
return out;
}
template<typename T>
ostream& operator>>(istream& in, Polynominal<T>& x) {
x.AddTerms(in);
return in;
}
template<typename T>
void Polynominal<T>::Output(ostream& out)const {
bool start = true;
Term<T>* p = theList->link;
for (; p != theList; p=p->link) {
if (!start && p->coef > 0)
out << '+';
start = false;
out << *p;
}
out << endl;
}
末尾📖
如果有帮助的话麻烦点个赞鼓励一下!
#include<iostream>
using namespace std;
template <typename T>
struct Term {
Term(int e) :exp(e),coef(0) { this->link = NULL; }
Term(T c, int e, Term* next) :coef(c), exp(e) { this->link = next; }
Term* InsertAfter(T c, int e);
T coef; //系数
int exp; //指数
Term* link; //下一项
};
template< typename T>
Term<T>* Term<T>::InsertAfter(T c, int e) {
link = new Term(c, e, link);
return link;
}
template <typename T>
ostream& operator<<(ostream& out, const Term<T>& val) {
if (val.coef == 0)
return out;
switch (val.exp) {
case 0:
out << val.coef;
break;
case 1:
if (val.coef != 1)
out << val.coef;
out << "X";
break;
default:
if (val.coef != 1)
out << val.coef;
out << "X^"<<val.exp;
break;
}
return out;
}
template<typename T>
class Polynominal {
public:
Polynominal();
~Polynominal();
void AddTerms(istream& in); //输入多项式
void Output(ostream& out)const; //输出多项式
Polynominal& PolyAdd(const Polynominal& x, const Polynominal& y); //多项式加法
Polynominal& PolyMul(const Polynominal& x, const Polynominal& y); //多项式相乘
void operator=(const Polynominal&x); //重载“=”运算符
void Clear();
private:
Term<T>* theList;
friend ostream& operator<<(ostream&, const Polynominal);
friend ostream& operator>>(istream&, Polynominal);
};
template<typename T>
Polynominal<T>::Polynominal() {
theList = new Term<T>(-1);
theList->link = theList;
}
template<typename T>
Polynominal<T>::~Polynominal() {
Clear();
delete theList;
}
template<typename T>
void Polynominal<T>::Clear() {
Term<T>* q = theList, * r;
for (r = q->link; r != theList; r = q->link) {
q->link = r->link;
delete r;
}
}
template< typename T>
void Polynominal<T>::AddTerms(istream& in) {
Term<T>* q = theList;
T c;
int e;
cout << "输入多项式系数与指数(coef,exp),指数为负数时停止输入\n" << endl;
for (;;) {
cin >> c >> e;
if (e < 0) //如果e为负值,输入完毕
break;
q = q->InsertAfter(c, e);
}
}
template<typename T>
ostream& operator<<(ostream& out, const Polynominal<T>& x) {
x.Output(out);
return out;
}
template<typename T>
ostream& operator>>(istream& in, Polynominal<T>& x) {
x.AddTerms(in);
return in;
}
template<typename T>
void Polynominal<T>::Output(ostream& out)const {
bool start = true;
Term<T>* p = theList->link;
for (; p != theList; p=p->link) {
if (!start && p->coef > 0)
out << '+';
start = false;
out << *p;
}
out << endl;
}
int ExpComp(int x, int y) {
if (x == y)
return 0;
else if (x > y)
return 1;
else
return -1;
}
template<typename T>
Polynominal<T>& Polynominal<T>::PolyAdd(const Polynominal<T>& x, const Polynominal<T>& y) {
Clear();
Term<T>* t = theList, * p = x.theList->link, * q = y.theList->link;
while (p->exp >= 0 || q->exp >= 0) {
switch (ExpComp(p->exp, q->exp)) {
case -1:
t->InsertAfter(q->coef, q->exp);
q = q->link;
break;
case 0:
if (p->coef + q->coef != 0)
t = t->InsertAfter(p->coef + q->coef, p->exp);
p = p->link;
q = q->link;
break;
case 1:
t->InsertAfter(p->coef, p->exp);
p = p->link;
break;
}
}
return *this;
}
template<typename T>
void Polynominal<T>::operator=(const Polynominal<T>& x) {
if (this == &x)//防止自我拷贝
return;
Clear();
Term<T>* q = theList, * p = x.theList->link;
for (; p != x.theList; p = p->link)
q = q->InsertAfter(p->coef, p->exp);
}
template<typename T>
Polynominal<T>& Polynominal<T>::PolyMul(const Polynominal& x, const Polynominal& y) {
Clear();
Polynominal<T> s, t;
Term<T>* q, * p = y.theList->link;
for (; p != y.theList; p = p->link) {
s = x;
for (q = s.theList->link; q != s.theList; q = q->link) {
q->coef = p->coef * q->coef;
q->exp = p->exp + q->exp;
}
t = PolyAdd(s, t);
}
return *this;
}
int main() {
Polynominal<int>a;
a.AddTerms(cin);
Polynominal<int>b;
b.AddTerms(cin);
cout << "输入:\n" << endl;
cout << "多项式q(x)=";
a.Output(cout);
cout << "多项式p(x)=";
b.Output(cout);
cout << "\n输出:\n";
Polynominal<int>c;
c.PolyMul(a, b);
cout << "q(x)×p(x)=";
c.Output(cout);
system("pause");
return 0;
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)