实现带freelist 的带头、尾结点的双向链表类并用其实现2个一元多项式的加法和乘法运算

1. 实现用freelist 的带头、尾结点的双向链表类的定义,实现双向链表的基本操作。`
a.因为要实现多项式的运算,所以每个结点存储了该项的系 数和该项的指数)
b.带freelist则注意重写他的new和delete方法,并且在外面实例化freelist.
c.在这个实现里还需要注意除了prev(),moveToStart()【移到表头】,moveToEnd()【移到表尾】,moveToFirst()【移到表头的下一个元素】,next()这几个函数能改变curr指针的位置,其余的操作,比如insert(),append(),都是不会改变curr指针的位置的。

#include<iostream>

using namespace std;

template <typename E> 
class Link  // the node
{
private:
	static Link<E>* freelist;
public:
	E element; //该项的系数
    E ezhinum;  //该项的指数
	Link* next; //后结点 
	Link* prev;//前结点 

	//constructure function
	Link(const E itnum, const E itzhi, Link* prevp, Link* nextp)
	{
		element = itnum;
        ezhinum  = itzhi;
		prev = prevp;
		next = nextp;
	}
	Link(Link* prevp = NULL, Link* nextp = NULL)   
	{
		prev = prevp;
		next = nextp;
	}
 
	//overloaded "new" operator,
	void* operator new(size_t) 
	{
		if (freelist == nullptr)
			return ::new Link; 
		Link<E>* temp = freelist;
		freelist = freelist->next; 
		return temp;
	}
	//overloaded "delete" opetator
	void operator delete(void* ptr)
	{
		((Link<E>*) ptr)->next = freelist; 
		freelist = (Link<E>*) ptr; 
	}
};

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


template <typename E> 
class Doublelist  // 双向链表 
{
private:
	Link<E>* head;
	Link<E>* tail;  //both tail and head has no element and ezhinum
	Link<E>* curr;
	int cnt;
	void init()  //initialization
	{
		curr = head =new Link<E>;
		tail =new Link<E>;  
		curr->next = tail;
		tail->prev = curr;
		cnt = 0;
	}

	void removeall()
	{
		while (head != NULL)
		{
			curr = head;
			head = head->next;
			delete curr;
		}
	}
public:
	Doublelist()  //construction
	{
		init();
	}
	Doublelist(Doublelist<E>&& L)   // copy
	{
		this->head = L.head;
		this->tail = L.tail;
		this->curr = L.curr;
		this->cnt = L.cnt;
		L.head = NULL;
		L.tail = NULL;
		L.curr = NULL;
		L.cnt = 0;
	}
	~Doublelist()
	{
		removeall();								
	}
	Doublelist<E>& operator = (Doublelist<E>&& L)  //override = 
	{
		this->head = L.head;
		this->tail = L.tail;
		this->curr = L.curr;
		this->cnt = L.cnt;
		L.head = NULL;
		L.tail = NULL;
		L.curr = NULL;
		L.cnt = 0;
		return *this;
	}
	void clear()
	{
		removeall();
		init();
	}
	void insert(const E& itnum, const E& itzhi)  //insert a node at curr position
	{
		curr->next = curr->next->prev = new Link<E>(itnum, itzhi, curr, curr->next); 
		cnt++;
	}
	void append(const E& itnum, const E& itzhi)  //append a node at the end of the list(before tail)
	{
		auto newnode = new Link<E>(itnum, itzhi, tail->prev, tail);
		tail->prev->next = newnode; // move the next pointer of the node before tail to newnode
		tail->prev = newnode; //set the prev pointer of tail to newnode
		cnt++;  //长度+1 
	}
	E remove()
	{
		if (curr->next == tail)
			return NULL;
		E itnum = curr->next->element;
		E itzhi = curr->next->ezhinum;
		Link<E>* temp = curr->next;
		curr->next->next->prev = curr;  
		curr->next = curr->next->next;  
		delete temp;
		cnt--;
		return itnum;
	}
    E currEle() 
    {
        return curr->element;
    }

    E currNum()
    {
        return curr->ezhinum;
    }
    
    void changecurr(const E & it)
    {
        curr->element += it;
    }
	void prev()
	{
		if (curr != head)
			curr = curr->prev;
	}
	void moveToStart()
	{
		curr = head;
	}
    void moveToFirst()  //move to the first actual node
    {
        curr = head->next;
    }
	void moveToEnd()
	{
		curr = tail;
	}
	void next()
	{
		if (curr != tail)
			curr = curr->next;
	}

    bool istail()
    {
        return curr==tail;
    }

	int length() const
	{
		return cnt;
	}
    void print()  //print the node's element and elezhinum from the first one to the last one
    {
        moveToFirst();
        cout << cnt << endl;
        for(int i=0; i<cnt; i++)
        {
            cout << curr->element << " " << curr->ezhinum << endl;
            curr = curr->next;
        }
    }

};

2. 实现两个多项式的加法
要求:运算结果得到的链表要求按照指数降序排列的多项式。

思路:用一个新的链表C存储结果,依次比较两个链表A,B,将指数较大且唯一的该项直接加入到C中,该链表curr指针向后移一位;如果指数相同且系数相加不为零,将相加后的结点加入C中,A,B的curr指针均向后移一位。重复上述步骤,直到有一个curr指针指向了链表的tail结点。然后将没有遍历完的那一个链表后面的结点直接加入C中。

Doublelist<int> add(Doublelist<int> &A, Doublelist<int> &B)
{
    Doublelist<int> newone;
    A.moveToFirst();
    B.moveToFirst();
    int countA = A.length();
    int countB = B.length();
    while(true)
    {
        if(A.currNum() == B.currNum())
        {
            if(A.currEle()+B.currEle()!=0)
            {
                newone.append(A.currEle()+B.currEle(),A.currNum());
            }
            countA--;
            countB--;
            A.next();
            B.next();
        }
        else if(A.currNum() > B.currNum())
        {
            newone.append(A.currEle(),A.currNum());
            A.next();
            countA--;
        }
        else if(A.currNum() < B.currNum())
        {
            newone.append(B.currEle(),B.currNum());
            B.next();
            countB--;
        }
        if(countA==0 || countB==0)
        {
            break;
        }
    }
    // find the list that hasn't move to tail and continue
    if(countA==0 && countB!=0)
    {
        while(countB != 0)
        {
            newone.append(B.currEle(),B.currNum());
            B.next();
            countB--;
        }
    }
    else if(countB==0 && countA!=0)
    {
        while(countA != 0)
        {
            newone.append(A.currEle(),A.currNum());
            A.next();
            countA--;
        }
    }
    return newone;
};

3.实现两个多项式的乘法
要求:运算结果得到的链表要求按照指数降序排列的多项式。

思路:用一个新的链表C存储结果,以A链表为基准,不断遍历B链表,将B链表结点与当前A链表结点相乘,B链表到达链表尾部后,将其curr指针指回第一个元素,A链表的curr指针向后移一位,直到A链表curr指针到达队尾。在A链表与B链表结点相乘的时候,需要比较新的结点的指数与C链表已有的结点指数的大小,如果比他大就插到他前面,否则就加到他后面。

Doublelist<int> multiple(Doublelist<int> &A, Doublelist<int> &B)
{
    Doublelist<int> newone;
    A.moveToFirst();
    B.moveToFirst();
    int countA = A.length();
    int countB = B.length();
    while(countA!=0)
    {
        if(countA==A.length())
        {
            for(int i=0; i<countB; i++)
            {
                newone.append(A.currEle()*B.currEle(),A.currNum()+B.currNum());
                B.next();
                newone.next();
            }
           B.moveToFirst();
        }
        else
        {
            for(int i=0; i<countB; i++)
            {
                int newele = A.currEle() * B.currEle();
                int newnum = A.currNum()+ B.currNum();
                if(newnum > newone.currNum())
                {
                    newone.prev();
                    int s = 0;
                    while(newone.currNum()<newnum)
                    {
                        newone.prev();
                        s++;
                    }
                    if(newone.currNum()==newnum)
                    {
                        if(newone.currEle()+newele!=0)
                        {
                            newone.changecurr(newnum);
                        }
                        else
                            newone.remove();
                    }
                    else 
                    {
                        newone.insert(newele,newnum);
                        
                    }
                    for(int i=0; i<s; i++)
                    {
                        newone.next();
                    }
                    if(countB!=1)
                    {
                        B.next();
                    }
                    
                    
                }
                else if(newnum == newone.currNum())
                {
                    if(newele + newone.currEle()!=0)
                    {
                        newone.changecurr(newele);
                        newone.next();
                    }
                    else
                    {
                        newone.remove();
                    }
                    
                    if(countB!=1)
                    {
                        B.next();
                    }
                    
                }
                else
                {
                    newone.append(newele,newnum);
                    newone.next();
                    if(countB!=1)
                    {
                        B.next();
                    }
                    
                }

            }
            B.moveToFirst();
            
        }
        countA--;
        A.next();
    }
    return newone;
}

4.输入输出示例,main函数

输入格式:
    3 2    //第一行,两个正整数分别表示多项式的项数
    5 4   //输入第一个多项式各项的系数和指数,按指数降序输入
    -3 2
    1 0   //第一个多项式:5x4-3x2+1
    6 2   //输入第二个多项式各项的系数和指数,按指数降序输入
    -3 1  //第二个多项式:6x2-3x
输出格式:
    4    //相加得到的多项式的项数
    5 4  //每一项的系数与指数,按指数降序排列输出
    3 2
    -3 1
    1 0   //和:5x4+3x2-3x+1
    6    //相乘得到的多项式的项数
    30 6
    -15 5
    -13 4
    9 3
    6 2
   -3 1   //乘积:30x6-18x5-13x4+9x3+6x2-3x

main函数

int main()
{
	int num1, num2;
    cin >> num1 >> num2;
    int ele, num;
    Doublelist<int> firstone;
    Doublelist<int> secondone;
    for(int i=0; i<num1; i++)
    {
        cin >> ele >> num;
        firstone.append(ele,num);
    }
    for(int i=0; i<num2; i++)
    {
        cin >> ele >> num;
        secondone.append(ele,num);
    }
    
    Doublelist<int> addlist = add(firstone,secondone);
    addlist.print();
    Doublelist<int> mullist = multiple(firstone,secondone);
    mullist.print();
    system("pause");
    return 0;

};

这竟然还不关注收藏点赞?!!!
快来一起打败可pia的程序和算法叭!!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值