繁体   English   中英

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

[英]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.hClassName.inlClassName.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文件保留给编译器用来构建目标代码,而头文件HINL都用于在编译和链接期间进行查找。 内联文件的使用使您的定义保持不变-实现与声明分开!

我将尝试简化您的类以便于阅读,同时将声明与定义分开。

单项式

#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 #definesstructure ,并将它们移到需要它们的Polynomial类中。

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

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

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

我看到您正在设置Monomial <>类型的传入参数的系数和指数,这可能有助于在Monomial类中定义赋值运算符。 您可能还希望将其他运算符以及+,+ =,*,* =等添加到Monomial类中。

至于添加两个具有相等指数的单项式的实现的方法是正确的,您已经具有比较运算符供您查看它们是否相等,然后在添加两个单项式: AB时,您需要添加两个答案并将其存储在一个临时容器中,然后从列表中删除您一起添加的两个答案,继续此过程,直到无法再添加任何术语为止。 然后使用所有临时存储的术语并重新填充班级列表。

您必须记住,多项式中的数值运算符用于将两个多项式相加和相乘。 如果尝试将两个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM