利用双链表实现2个一元多项式的加法和乘法运算

数据结构实验——利用双链表实现2个一元多项式的加法和乘法运算

本周数据结构实验,题目如下,前前后后三天写了十多个小时,终于写的我感觉比较满意了
1.编写使用freelist 的带头、尾结点的双向链表类的定义,实现双向链表的基本操作。
2.利用双向链表实现2个一元多项式的加法和乘法运算,运算结果得到的链表要求按照指数降序排列的多项式。
输入格式:

3 2   //第一行,两个正整数分别表示两个多项式的项数
5 4   //输入第一个多项式各项的系数和指数,按指数降序输入
-3 2
1 0   //第一个多项式:5x⁴-3x²+1
6 2   //输入第二个多项式各项的系数和指数,按指数降序输入
-3 1  //第二个多项式:6x²-3x

输出格式:

4    //相加得到的多项式的项数
5 4  //每一项的系数与指数,按指数降序排列输出
3 2
-3 1
1 0   //和:5x⁴+3x²-3x+1
6    //相乘得到的多项式的项数
30 6
-15 5
-18 4
9 3
6 2
-3 1   //乘积:30x⁶-15x⁵-18x⁴+9x³+6x²-3x

设计算法

这道题写类还是很好写的,这里我的类采用的是curr指向当前结点,因为这样操作会稍微方便一点。接下来主要就是写两个函数add和mult用于计算加法和乘法。其实写出来了发现加法和乘法都不难。
加法: 其实加法很简单,就是一个一个比较指数,指数相同则系数相加,得到一个新的结点;指数不同,则把指数大的一个构成一个新的结点;
乘法: 乘法稍微麻烦一些,但是就跟我们学的数学一样,一个一个系数相乘,指数相加,得到结点之后,和前面计算的相比较,按照加法的操作来就对了

C++实现:

双链表类头文件(pro.h):

#ifndef PRO
#define PRO

//采用可利用空间表的双链表
template <typename E> class Link
{
private:
    static Link<E>* freelist;
public:
    E num1;                     //系数的值
    E num2;                     //指数的值
    Link* prev;                 //指向双链表的前一节点
    Link* next;                 //指向双链表的后一节点

    Link(const E& a,const E& b,Link* prevp,Link* nextp)              //创建一个节点
    {
        num1=a;
        num2=b;
        prev=prevp;
        next=nextp;
    }
    Link(Link* prevp=NULL,Link* nextp=NULL)                    //创建头节点或尾节点
    {
        prev=prevp;
        next=nextp;
    }

    void* operator new(size_t)                     //重载new运算符
    {
        if(freelist == NULL)  return ::new Link;
        Link<E>* temp=freelist;
        freelist=freelist->next;
        return temp;
    }
    void operator delete(void* ptr)               //重载delete运算符号
    {
        ((Link<E>*)ptr)->next=freelist;
        freelist=(Link<E>*)ptr;
    }
};

template <typename E>
Link<E>* Link<E>::freelist = NULL;

template <typename E> class List          
{
private:
    Link<E>* head;     
    Link<E>* tail;
    Link<E>* curr;
    int cnt;

    void init()                       //初始化,创建头节点和尾节点,curr指向头节点
    {
        curr=head=new Link<E>;
        tail=new Link<E>;
        head->next=tail;
        tail->prev=head;
        cnt=0;
    }
    void removeall()                 //删除所有节点
    {
        while(head!=NULL)
        {
            curr=head;
            head=head->next;
            delete curr;
        }
    }
public:
    List() {init();}
    ~List() {removeall();}
    void print()   const;
    void clear()  { removeall();init();}            
    void insert(const E& a,const E& b)                        //插入一个新的结点
    {
        curr->prev=curr->prev->next=new Link<E>(a,b,curr->prev,curr);
        cnt++;
    }

    void append(const E& a,const E& b)                       //在尾节点之前添加一个新节点
    {
        tail->prev = tail->prev->next = new Link<E>(a,b,tail->prev,tail);
        cnt++; 
    }

    void remove()                          //删除一个指定的节点
    {
        if(curr==tail)
            return;
        Link<E>* Itemp=curr;
        curr->prev->next=curr->next;
        curr->next->prev=curr->prev;
        delete Itemp;
        cnt--;
    }

    void moveToStart()                 //curr指向头节点
    {
        curr=head;
    }

    void moveToEnd()                  //curr指向尾节点
    {
        curr=tail;
    }

    void prev()                      //curr指向前一个结点
    {
        if(curr!=head)
            curr=curr->prev;
    }

    void next()                     //curr指向下一个节点
    {
        if(curr!=tail)  curr=curr->next;
    }

    int length() const  {return cnt;}                //双链表节点的个数


    int currPos()  const                    //curr现在的位置
    {
        Link<E>* temp=head;
        int i;
        for(i=0;temp!=curr;++i)
            temp=temp->next;
        return i;
    }

    void moveToPos(int pos)                 //curr移动到指定位置
    {
        assert ((pos>=0)&&(pos<=cnt));
        curr=head;
        for(int i=0;i<pos;++i)  curr=curr->next; 
    }

    void get_begin()                     //curr指向第一个节点
    {
        curr=head->next;
    }

    const E& getValue1() const           //得到系数的值
    {
        return curr->num1;
    }

    const E& getValue2() const            //得到指数的值
    {
        return curr->num2;
    }

    void changeValue1(E n)
    {
        curr->num1+=n;
    }

    void changeValue2(E n)
    {
        curr->num1+=n;
    } 
};

#endif //PRO

源文件(pro.cpp):

#include<iostream>
#include<cassert>
#include"pro.h"
using namespace std;

int N,M;
List<int> L1,L2;

void read()                       //读入一元多项式
{
    cin>>N>>M;
    for(int i=0;i<N;++i)
    {
        int a,b;
        cin>>a>>b;
        L1.append(a,b);
    }
    for(int j=0;j<M;++j)
    {
        int c,d;
        cin>>c>>d;
        L2.append(c,d);
    }
}

List<int> add(List<int> &A,List<int> &B)        //计算两个一元多项式相加得到的新一元多项式
{
    List<int> L3;
    A.get_begin();
    B.get_begin();
    int lenA=A.length();
    int lenB=B.length();

    while(true)
    {
        if(A.getValue2() == B.getValue2())          //如果两个指数相等,则将系数相加,得到新的节点添加到L3尾部
        {
            if(A.getValue1()+B.getValue1()!=0)
                L3.append(A.getValue1()+B.getValue1(),A.getValue2());
            A.next();
            B.next(); 
        }
        else if(A.getValue2()>B.getValue2())       //如果其中一个指数较大,直接将该结点添加到L3的尾部
        {
            L3.append(A.getValue1(),A.getValue2());
            A.next();
        }
        else
        {
            L3.append(B.getValue1(),B.getValue2());
            B.next();
        }

        if(A.currPos()>A.length() || B.currPos()>B.length())     //其中一个双链表遍历完,结束循环
            break;
    }

    //将另外一个没有遍历完的双链表剩余结点添加到L3的尾部
    if(A.currPos()>A.length() && B.currPos()>B.length())
    {}
    else if(A.currPos()>A.length())            
    {
        while(true)
        {
            L3.append(B.getValue1(),B.getValue2());
            B.next();
            if(B.currPos()>B.length())
                break;
        }
    }
    else
    {
        while(true)
        {
            L3.append(A.getValue1(),A.getValue2());
            A.next();
            if(A.currPos()>A.length())
                break;
        }        
    }
    return L3;
}

List<int> mult(List<int> &C,List<int> &D)           //计算两个一元多项式相乘所得到新的一元多项式
{
    List<int> L;
    int i=0;

    C.get_begin();
    while(C.currPos()<=C.length())
    {
        D.get_begin();
        i+=1;
        while(D.currPos()<=D.length())
        {
            L.get_begin();
            int mul_coef=C.getValue1()*D.getValue1();       //系数相乘
            int mul_expon=C.getValue2()+D.getValue2();      //指数相加
            if(i>1)
            {
                for(int j=0;j<L.length();++j)
                {
                    if(mul_expon<L.getValue2()&&j!=L.length()-1)      //指数小于当前结点指数且没到最后一个结点,则指向下一个结点
                        L.next();
                    else if(mul_expon<L.getValue2()&&j==L.length()-1)           //指数小于当前结点指数且到了最后一个结点,则把该结点加到末尾
                    {
                        L.append(mul_coef,mul_expon);
                        break;
                    }
                    else if(mul_expon==L.getValue2())           //指数相同,则系数相加,得到新的结点同时删掉原本的结点
                    {
                        if(mul_coef+L.getValue1()!=0)
                            L.changeValue1(mul_coef);
                        else
                            L.remove();
                        break;
                    }
                    else                                   //指数大于当前节点指数,则插入该结点
                    {
                        L.insert(mul_coef,mul_expon);
                        break;
                    }       
                }
            }
            else                           //第一次运算直接将所有结果加到L中,无需比较
            {
                L.append(mul_coef,mul_expon);
            }
            D.next();
        }
        C.next();
    }
    return L;
}

void print(List<int> E)              //输出双链表所表示一元多项式的数据
{
    E.get_begin();
    cout<<E.length()<<endl;
    for(int i=0;i<E.length();++i)
    {
        cout<<E.getValue1()<<" "<<E.getValue2()<<endl;
        E.next();
    } 
}

int main()
{
    read();
    print(add(L1,L2));
    print(mult(L1,L2));
    return 0;
}
发布了82 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Slatter/article/details/102581948