如何使用链表和单项类C ++实现多项式类

时间:2015-10-06 02:59:37

标签: c++ list

所以我需要为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++;
}

显然,如果列表为空,我仍然需要对它进行说明,如果找不到指数匹配,那该怎么办呢。但是现在我只想要一个简单的单项式多项式函数作为例子来构建我的其他函数。

2 个答案:

答案 0 :(得分:1)

在查看您的类声明后,我可以看到一些问题,并会尝试使用注释来标记现有代码以帮助您解决问题。我还建议,由于您的课程是模板,因此您应该为课程提供3个文件:ClassName.hClassName.inl&amp; 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 指令之前。 s保护它应该是一个内联文件,如 ClassName.inl 这样任何类型的内联方法都不在 ClassName.cpp中 文件或任何模板函数都在此实现文件中定义,这是另一种形式的头文件。您的 CPP 文件保留给编译器以构建目标代码和头文件 H &amp; INL 用于在编译和链接期间查找。使用内联文件可以保持您的定义 - 实现与您的声明分开!

我将尝试简化您的类,以便在将声明与定义分开时更容易阅读。

<强> Monomial.h

#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.inl

// -------------------------------------------------------------------------
// 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!=

<强> Monomial.cpp

#include "Monomial.h"

<强> Polynomial.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.inl

// -------------------------------------------------------------------------
// 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

<强> Polynomial.cpp

#include "Polynomial.h"

这种布局样式将声明与定义分开,使代码更易于阅读并允许其模块化。通过这种方式,使用您的课程的人或用户不必担心这些功能如何工作,他们只需要查看他们返回的内容的声明以及他们接受的参数以及对什么类型的任务的基本描述功能/方法执行。我还删除了Monomial类中不需要的一些代码行,因为它们仅被多项式类#includes使用,#defines&amp; structure并将它们移动到需要它们的多项式类中。

现在关于如何执行您在问题中展示的特定任务的问题,例如如何添加,我可以根据您已经显示的内容为您提供一些建议。

如果要创建一个名为temp的Monomial类型的堆栈变量,则需要使用模板括号作为变量:

Monomial<NumberType> temp; // You did define Monomial as a template type.

我看到你正在设置系数和&amp;您传入的Monomial&lt;&gt;参数的指数在类型中,在Monomial类中定义赋值运算符会很有帮助。您可能还希望将其他运算符添加到您的Monomial类以及+,+ =,*,* =等。

至于你实现添加两个具有相同指数的单项式,你是在正确的轨道上,你已经有了比较运算符供你查看它们是否相等,那么当两个单项式时: &amp;可以添加 B ,您需要添加两个并将答案存储在临时容器中,并从列表中删除您一起添加的两个,继续此过程直到不再可以添加条款。然后获取所有临时存储的术语并重新填充您的课程列表。

你必须记住,多项式中的数值运算符用于添加&amp;将两个多项式相乘。如果您尝试将两个Monomials一起添加,那么您将需要Monomial类中的运算符。

答案 1 :(得分:1)

为什么我不喜欢回答这样的问题:为了回答这个问题,你最终会做一半人的家庭作业。也许他们学习,也许他们不会,但是告诉你什么。剪切和粘贴可以让你通过课堂,但它会让你在现实生活中提供咖啡和销售手机。

我甚至没有尝试优化此代码。多项式+ =多项式算子是最糟糕的方法。写作也是最快的。

行。 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;
}

我玩弄了非常常的非引用toadd,因为有人被复制了,但是躲了起来,去了熟悉的地方。我不会使用返回玩游戏,因为它是一个复制的简单对象,如果编译器看到需要,任何构造函数逻辑可能都是elided

friend std::ostream& operator<<(std::ostream & out,
                                const Monomial<NumT> & rhs)
{
    out << rhs.coeff << '^' << rhs.expo;
    return out;
}

标准&lt;&lt;覆盖以测试结果。

我在课堂上完全写的Polynomial类。 There is usually nothing to be gained from spinning off the implementation of a template这也不例外。

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;
}

我摆脱了排序。每次排序和求助并不重要。因为Polynomial是围绕std :: list构建的,所以每次排序都是你可能不得不做的O(n)。列表修改后排序或根本不排序。无论如何,我使用了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;
}

再次&lt;&lt;过载,便于测试。

最后一些测试代码,以确保我没有完全破解。

#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;
}