[英]How to implement polynomial class using linked list and monomial class C++
因此,我需要为Monomials创建两个类。 另一个用于多项式(使用单项式链接列表构建)。
我已经完成了函数声明,现在需要进入定义,这就是我遇到的问题。
我认为,如果我对一个函数有一定的了解,就可以编写其余的函数。 这是我要遵循的方向,不确定是否正确。 如果不是,您能指出我正确的方向吗? 从来没有使用过迭代器,所以这真的让我失望了。 这是我的头
#ifndef __POLYNOMIAL_H_
#define __POLYNOMIAL_H_
#include <iostream>
#include <list>
#include "Polynomial.cpp"
#define var = 'x' //varible to use in polynomial
using namespace std;
struct ZERO_T {
static const short ZERO = 0;
};
template <typename NumT>
class Monomial
{
public:
Monomial<NumT>(NumT c = 0, int d = 0) : coeff(c), expo(d)
{ };
NumT coefficient(void) const { return coeff; };
int degree(void) const { return expo; };
void assign_coefficient(const NumT c) { coeff = c; };
void assign_degree(const int d) { expo = d; };
bool operator==(const Monomial<NumT> & m) const
{
return (coeff == m.coeff && expo == m.expo);};
bool operator!=(const Monomial<NumT> & m) const
{return (coeff != m.coeff || expo != m.expo);};
private:
NumT coeff;
int expo;
};
template <typename NumberType>
class Polynomial : public ZERO_T
{
public:
Polynomial<NumberType>(NumberType c = 0, int d = 0)
{
const Monomial<NumberType> m(c, d);
term_list.push_back(m); //creates a ZERO monomial
number_of_terms = 1;
highest_degree = d;
}
Polynomial<NumberType>(const Monomial<NumberType> & m) //type conversion constructor
{
term_list.push_back(m);
number_of_terms = 1;
highest_degree = m.degree();
}
~Polynomial<NumberType>() { } // use default destructors and list's destructor
Polynomial<NumberType>(const Polynomial<NumberType> & rhs) // copy constructor
: term_list(rhs.term_list), number_of_terms(rhs.number_of_terms),
highest_degree(rhs.highest_degree) { }
const Polynomial<NumberType> & operator=(const Polynomial<NumberType> & rhs);
//copy assignment
Polynomial<NumberType> operator+=(const Monomial<NumberType> &m);
Polynomial<NumberType> operator+=(const Polynomial<NumberType> & rhs);
const Polynomial<NumberType> operator+(const Monomial<NumberType> &m)const;
const Polynomial<NumberType> operator+(const Polynomial<NumberType> & rhs) const;
Polynomial<NumberType> operator*=(const Monomial<NumberType> &m);
Polynomial<NumberType> operator*=(const Polynomial<NumberType> & rhs);
const Polynomial<NumberType> operator*(const Monomial<NumberType> &m) const;
const Polynomial<NumberType> operator*(constPolynomial<NumberType> & rhs) const;
const NumberType evaluate(NumberType x);
bool operator==(const Polynomial<NumberType> &p) const;
bool operator!=(const Polynomial<NumberType> &p) const;
const int gethighestdegree();
void read(istream & in = cin);
void print(ostream & out = cout) const;
//static Polynomial<NumberType> ZERO;
private:
list<Monomial<NumberType> > term_list;
//sorted by decreasing degrees
int number_of_terms;
int highest_degree;
void insert_in_poly(Polynomial<NumberType> & p, const Monomial<NumberType> & m);
//helper function
NumberType power(NumberType x, int n);
};
//template<> Polynomial<int> Polynomial<int>::ZERO = 0;
template <typename NumberType>
istream&operator>>(istream & in, Polynomial<NumberType> & rhs);
template <typename NumberType>
ostream& operator<<(ostream & out, const Polynomial<NumberType> & rhs);
#include "polynomial.cpp"
#endif
您将如何添加? 这是我到目前为止的内容:
#ifndef __POLYNOMIAL_CPP_
#define __POLYNOMIAL_CPP_
#include <iostream>
#include <cmath>
#include <list>
#include "polynomial.h"
#endif
template<typename NumberType>
const Polynomial<NumberType> Polynomial<NumberType>::operator+(const Monomial<NumberType>& m) const
{
int i = 0;
term_list.sort(); //sort list in decending order
term_list.reverse(); //rearrange into ascending order
Monomial temp; //create a temp object to hold our monomial
temp.coeff = m.coeff;
temp.expo = m.expo;
/////////////////experiments here/////////
list <Monomial<NumberType>>::iterator itr;
itr = p.termlist.begin();
while (itr != p.termlist.end()) //traverse termlist until we reach end
{
if (itr.expo == temp.expo) //if temp exponents meet current list exponent
itr insert(i, NumberType& temp); //insert monomial here
else
i++;
}
显然,如果列表为空,并且如果从未找到指数匹配,该怎么办呢? 但是现在,我只想简单地将多项式添加到多项式函数中,以作为构建其他函数的示例。
查看您的类声明后,我会看到一些问题,并将尝试用注释标记您现有的代码以帮助您。 我还将建议,由于您的类是模板,因此您应该为该类提供3个文件: ClassName.h
, ClassName.inl
和ClassName.cpp
这将因模板的行为而长期帮助您。 在您的常规代码中添加注释之后,我将尝试重新构建类,就像它们出现在各自文件中一样。
这就是你所拥有的
#ifndef __POLYNOMIAL_H_
#define __POLYNOMIAL_H_
#include <iostream>
#include <list>
#include "Polynomial.cpp" // Why including *.cpp?
#define var = 'x' //varible to use in polynomial
using namespace std;
struct ZERO_T {
static const short ZERO = 0;
};
template <typename NumT>
class Monomial {
public:
Monomial<NumT>(NumT c = 0, int d = 0) : coeff(c), expo(d)
{ };
NumT coefficient(void) const { return coeff; };
int degree(void) const { return expo; };
void assign_coefficient(const NumT c) { coeff = c; };
void assign_degree(const int d) { expo = d; };
bool operator==(const Monomial<NumT> & m) const
{
return (coeff == m.coeff && expo == m.expo);};
bool operator!=(const Monomial<NumT> & m) const
{return (coeff != m.coeff || expo != m.expo);};
private:
NumT coeff;
int expo;
};
template <typename NumberType>
class Polynomial : public ZERO_T {
public:
Polynomial<NumberType>(NumberType c = 0, int d = 0) {
const Monomial<NumberType> m(c, d);
term_list.push_back(m); //creates a ZERO monomial
number_of_terms = 1;
highest_degree = d;
}
Polynomial<NumberType>(const Monomial<NumberType> & m) //type conversion constructor {
term_list.push_back(m);
number_of_terms = 1;
highest_degree = m.degree();
}
~Polynomial<NumberType>() { } // use default destructors and list's destructor
Polynomial<NumberType>(const Polynomial<NumberType> & rhs) // copy constructor
: term_list(rhs.term_list), number_of_terms(rhs.number_of_terms),
highest_degree(rhs.highest_degree) { }
const Polynomial<NumberType> & operator=(const Polynomial<NumberType> & rhs);
//copy assignment
Polynomial<NumberType> operator+=(const Monomial<NumberType> &m);
Polynomial<NumberType> operator+=(const Polynomial<NumberType> & rhs);
const Polynomial<NumberType> operator+(const Monomial<NumberType> &m)const;
const Polynomial<NumberType> operator+(const Polynomial<NumberType> & rhs) const;
Polynomial<NumberType> operator*=(const Monomial<NumberType> &m);
Polynomial<NumberType> operator*=(const Polynomial<NumberType> & rhs);
const Polynomial<NumberType> operator*(const Monomial<NumberType> &m) const;
const Polynomial<NumberType> operator*(constPolynomial<NumberType> & rhs) const;
const NumberType evaluate(NumberType x);
bool operator==(const Polynomial<NumberType> &p) const;
bool operator!=(const Polynomial<NumberType> &p) const;
const int gethighestdegree();
void read( istream & in = cin );
void print( ostream & out = cout ) const;
//static Polynomial<NumberType> ZERO;
private:
list<Monomial<NumberType> > term_list;
//sorted by decreasing degrees
int number_of_terms;
int highest_degree;
void insert_in_poly(Polynomial<NumberType> & p, const Monomial<NumberType> & m);
//helper function
NumberType power( NumberType x, int n );
};
//template<> Polynomial<int> Polynomial<int>::ZERO = 0;
template <typename NumberType>
istream& operator>>( istream & in, Polynomial<NumberType> & rhs );
template <typename NumberType>
ostream& operator<<( ostream & out, const Polynomial<NumberType> & rhs );
#include "polynomial.cpp" // Why include *.cpp?
#endif
如果您注意到我的评论, 为什么要包含Polynomial.cpp? 您永远都不想在另一个文件(尤其是头文件)中包含CPP文件。 如果您想要一个实现文件,可以将其包含在类定义之后,头文件保护措施的#endif指令之前的头文件底部,则该文件应为ClassName.inl中的内联文件,这样,任何类型的此实现文件(头文件的另一种形式)中定义了不在ClassName.cpp文件或任何模板函数中的内联方法。 您的CPP文件保留给编译器用来构建目标代码,而头文件H和INL都用于在编译和链接期间进行查找。 内联文件的使用使您的定义保持不变-实现与声明分开!
我将尝试简化您的类以便于阅读,同时将声明与定义分开。
单项式
#ifndef MONOMIAL_H
#define MONOMIAL_H
template<typename NumT>
class Monomial {
private:
NumT m_coeff;
int m_expo;
public:
explicit Monomial( NumT c = 0, int d = 0 ); // Added Explicit since both parameters can be defaulted
NumT coefficient() const;
int degree() const;
void assignCoefficient( const NumT c );
void assignDegree( const int d );
bool operator==( const Monomial<NumT>& other ) const;
bool operator!=( const Monomial<NumT>& other ) const;
private:
Monomial( const Monomial& c ); // Not Implemented - Copy Constructor
Monomial& operator=( const Monomial& c ); // Not Implemented - Assignment Operator
}; // Monomial
#include "Monomial.inl"
#endif // MONOMIAL_H
单项式
// -------------------------------------------------------------------------
// Monomial() - Constructor
template<typename NumT>
Monomial<NumT>::Monomial( NumT c, int d ) :
m_coeff( c ),
m_expo( d ) {
} // Monomial
// -------------------------------------------------------------------------
// coefficient()
template<typename NumT>
NumT Monomial<NumT>::coefficient() const {
return m_coeff;
} // coefficient
// -------------------------------------------------------------------------
// degree()
template<typename NumT>
int Monomial<NumT>::degree() const {
return m_expo;
} // degree
// -------------------------------------------------------------------------
// assignCoefficient()
template<typename NumT>
void Monomial<NumT>::assignCoefficient( const NumT c ) {
m_coeff = c;
} // assignCoefficient
// -------------------------------------------------------------------------
// assignDegree()
template<typename NumT>
void Monomial<NumT>::assignDegree( const int d ) {
m_expo = d;
} // assignDegree
// -------------------------------------------------------------------------
// operator==()
template<typename NumT>
bool Monomial<NumT>::operator==( const Monomial<NumT>& other ) const {
return ( m_coeff == other.m_coeff && m_expo == other.m_expo );
} // operator==
// -------------------------------------------------------------------------
// operator!=()
template<typename NumT>
bool Monomial<NumT>::operator!= ( const Monomial<NumT>& other ) const {
return ( m_coeff != other.m_coeff || m_expo != other.m_expo );
} // operator!=
单项
#include "Monomial.h"
多项式
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <iostream>
#include <list>
#include "Monomial.h"
#define var = 'x'
struct ZERO_T {
static const short ZERO = 0;
};
template<typename NumberType>
class Polynomial : public ZERO_T {
friend std::istream& operator>>( std::istream& in, const Polynomial<NumberType>& poly );
friend std::ostream& operator<<( std::ostream& out, const Polynomial<NumberType>& poly );
private:
list<Nomomial<NumberType>> m_lTerms;
int m_iNumTerms;
int m_iHighestDegree;
public:
// Constructors & Destructors
explicit Polynomial( NumberType c = 0, int d = 0 );
Polynomial( const Monomial<NumberType>& m );
Polynomial( const Polynomial<NumberType& rhs );
// ~Polynomial(); // Default Okay
// Assignment Operator
const Polynomial<NumberType>& operator=( const Polynomial<NumberType>& rhs );
// Comparison Operators
bool operator==( const Polynomial<NumberType>& p ) const;
bool operator!=( const Polynomial<NumberType>& p ) const;
bool operator<( const Polynomial<NumberType>& p ) const;
bool operator<=( const Polynomial<NumberType>& p ) const;
bool operator>( const Polynomial<NumberType>& p ) const;
bool operator>=( const Polynomial<NumberType>& p ) const;
// Numerical Operators
Polynomial<NumberType>& operator+=( const Monomial<NumberType>& m );
Polynomial<NumberType>& operator+=( const Polynomial<NumberType>& rhs );
Polynomial<NumberType> operator+( const Monomial<NumberType>& m ) const;
Polynomial<NumberType> operator+( const Polynomial<NumberType>& rhs ) const;
Polynomial<NumberType>& operator*=( const Monomial<NumberType>& m );
Polynomial<NumberType>& operator*=( const Polynomial<NumberType>& rhs );
Polynomial<NumberType> operator*( const Monomial<NumberType>& m ) const;
Polynomial<NumberType> operator*( const Polynomial<NumberType& rhs ) const;
// Public Member Functions
int getHighestDegree() const;
void read( std::istream& in = cin );
void print( std::ostream& out = cout ) const;
private:
void insertInPoly( Polynomial<NumberType>& p; const Monomial<NumberType>& m );
NumberType power( NumberType x, int n );
}; // Polynomial
#include "Polynomial.inl"
#endif // POLYNOMIAL_H
多项式
// -------------------------------------------------------------------------
// Polynomial()
// To save some time all of this class's implementations should be in here
// where template<typename T> needs to be defined, just as I did within
// Monomial.inl
多项式
#include "Polynomial.h"
这种布局样式将声明与定义分开,从而使代码更易于阅读,并使其模块化。 这样,使用您的类的个人或用户就不必担心这些函数的工作方式,他们只需要查看它们返回的内容和接受的参数的声明,以及对函数/方法执行。 我还删除了Monomial类中不需要的一些代码行,因为它们仅被Polynomial类#includes
#defines
, #includes
#defines
和structure
,并将它们移到需要它们的Polynomial类中。
现在,关于您如何执行问题中显示的特定任务(例如如何添加)的问题,我可以根据您已经显示的内容为您提供一些建议。
如果要创建名为temp的Monomial类型的堆栈变量,则需要使用变量的模板括号,如下所示:
Monomial<NumberType> temp; // You did define Monomial as a template type.
我看到您正在设置Monomial <>类型的传入参数的系数和指数,这可能有助于在Monomial类中定义赋值运算符。 您可能还希望将其他运算符以及+,+ =,*,* =等添加到Monomial类中。
至于添加两个具有相等指数的单项式的实现的方法是正确的,您已经具有比较运算符供您查看它们是否相等,然后在添加两个单项式: A和B时,您需要添加两个答案并将其存储在一个临时容器中,然后从列表中删除您一起添加的两个答案,继续此过程,直到无法再添加任何术语为止。 然后使用所有临时存储的术语并重新填充班级列表。
您必须记住,多项式中的数值运算符用于将两个多项式相加和相乘。 如果尝试将两个Monomials一起添加,则在此处需要Monomial类中的运算符。
为什么我不喜欢回答这样的问题:要回答问题,您需要完成某人的一半作业。 也许他们学到了,也许他们没有学到,但是林姆告诉了你一些事情。 剪切和粘贴可以使您上一堂课,但实际上却可以让您一边喝咖啡一边销售电话。
我什至没有尝试优化此代码。 多项式+ =多项式运算符是最糟糕的方法。 它也是最快写的。
好。 Monomial类大致相同。 我添加了两个方法和一个朋友函数。
Monomial& operator+=(const Monomial & toadd)
{
if (expo != toadd.expo)
{
throw "Mismatched exponents";
}
coeff += toadd.coeff;
return *this;
}
很简单 如果系数不匹配,则炸毁。 否则,添加系数并返回对修改后的对象的引用。
我从+ =开始,因为+是+ =用本地副本调用
Monomial operator+(const Monomial & toadd) const
{
return Monomial(*this) += toadd;
}
我开玩笑地传递了非const non引用来添加,因为有人被复制了,但w之以鼻,去找熟悉的人。 我不玩带有返回值的游戏,因为它是要复制的琐碎对象,如果编译器认为有需要,则可能会省略任何构造方法逻辑。
friend std::ostream& operator<<(std::ostream & out,
const Monomial<NumT> & rhs)
{
out << rhs.coeff << '^' << rhs.expo;
return out;
}
和标准<<覆盖以测试结果。
我完全在类内编写的多项式类。 分离模板的实现通常没有任何收获 ,这也不例外。
Polynomial & operator+=(const Monomial<NumberType> &m)
{
auto found = std::find_if(term_list.begin(),
term_list.end(),
[&m] (const Monomial<NumberType> &mono)
{
return mono.degree() == m.degree();
} );
if (found != term_list.end())
{
*found += m;
}
else
{
term_list.push_back(m);
highest_degree = std::max(m.degree(), highest_degree);
number_of_terms++; // pointless variable. Should always equal term_list.size()
}
return *this;
}
我摆脱了排序。 每次排序和重新排序都没有多大意义。 每次排序都是一个O(n),因为多项式是围绕std :: list构建的,所以您可能仍然必须这样做。 当列表被修改或根本不排序时进行排序。 无论如何,我使用了std :: find_if ,如果将来更改了容器,它可能会引入一些容器和排序优化,以进行查找。
Polynomial & operator+=(const Polynomial & rhs)
{
for (auto & mono: rhs.term_list)
{
*this += mono;
}
return *this;
}
这是我可以添加两个多项式的最懒惰,最愚蠢的方式。 rhs中的每个单项式都添加this
。 由于多项式+单项式将不存在的指数插入并添加到那些指数中,因此所有单项式将在结果中表示。 我很确定,只要稍加注意,时间复杂度就可以从O(n ^ 2)降低到O(n)。
const Polynomial operator+(const Monomial<NumberType> &m) const
{
return Polynomial (*this) += m;
}
const Polynomial operator+(const Polynomial & rhs) const
{
return Polynomial (*this) += rhs;
}
与上次操作员+相同,只需复制并调用+ =。
friend std::ostream& operator<<(std::ostream & out,
const Polynomial<NumberType> & rhs)
{
if (!rhs.term_list.empty())
{
auto mono = rhs.term_list.begin();
out << *mono;
for (++mono; mono != rhs.term_list.end();++mono)
{
out << " + " << *mono;
}
}
else
{
out << "empty";
}
return out;
}
再次是<< <<过载,易于测试。
最后,通过一些测试代码来确保我还不完全熟练。
#include <iostream>
#include "Polynomial.h"
using namespace std;
int main()
{
Polynomial<int> p;
p += Monomial<int>(100,0);
p += Monomial<int>(1,1);
p += Monomial<int>(0,2);
p += Monomial<int>(1,3)+Monomial<int>(1,3);
p += Monomial<int>(5,4);
cout << p<<endl;
auto p2 = p+ Monomial<int>(3,3);
cout << p2 << endl;
cout << p+p2<< endl;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.