数据结构实验——利用双链表实现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;
}