目录
1.题目
有序链表ADT模板简单应用算法设计:一元多项式的加/减法运算
作者: 冯向阳 时间限制: 1S 章节: DS:线性表
问题描述 :
目的:使用C++模板设计单链表的抽象数据类型(ADT)。并在此基础上,稍加改动,针对一元多项式建立相应的稀疏多项式ADT,使用单链表ADT的基本操作,设计并实现稀疏一元多项式的加法计算的算法设计。
内容:(1)请参照单链表的ADT模板,设计稀疏一元多项式的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考网盘中的单链表ADT原型文件,自行设计稀疏一元多项式的ADT。)
(2)ADT的简单应用:使用该ADT设计并实现稀疏一元多项式的加法计算的算法设计。
应用1:假设2个稀疏一元多项式分别由带头结点的有序单链表A和B存储。现要求设计一个算法,实现稀疏一元多项式的加减法计算。要求使用A和B的原存储空间,且计算后B不再单独存在。输入中的单链表的长度不得在计算算法中利用,仅作为建表使用。
假定:系数项的数据类型为double,指数项的数据类型为int,指数项递增有序,多项式至少有1项,系数项均不为0。
注意:加/减法计算后,如某一项的结果系数为0,则该项要从多项式链表中删除。
参考函数原型:
template<class ElemType1,class ElemType2>
void Add_Poly( poly_LinkList<ElemType> &A, poly_LinkList<ElemType> &B, int add_sub );
有序链表模板类原型(用于一元多项式计算)参考如下:
/* 单链表的结点定义 */(用于一元多项式计算)
template<class ElemType1, class ElemType2>
struct LinkNode
{
ElemType1 factor; //系数
ElemType2 indice; //指数
LinkNode<ElemType1, ElemType2> *next;
LinkNode(LinkNode<ElemType1, ElemType2> *ptr = NULL){next = ptr;} //构造函数1,用于构造头结点
LinkNode(const ElemType1 &item1, const ElemType2 &item2, LinkNode<ElemType1, ElemType2> *ptr = NULL) //构造函数2,用于构造其他结点
//函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
{
next = ptr;
factor = item1;
indice = item2;
}
ElemType1 getFactor(){ return factor;} //取得结点中的系数
ElemType2 getIndice(){ return indice;} //取得结点中的指数
void SetLink( LinkNode<ElemType1, ElemType2> *link ){ next = link; } //修改结点的next域
void SetFactor( ElemType1 value ){ factor = value; } //修改结点的系数
void SetIndice( ElemType2 value ){ indice = value; } //修改结点的指数
};//带头结点的单链表(用于一元多项式计算)
template<class ElemType1, class ElemType2>
class poly_LinkList{
private:
LinkNode<ElemType1, ElemType2> *head; // 头结点
LinkNode<ElemType1, ElemType2> *tail; // 尾结点
public:
//无参数的构造函数
poly_LinkList(){head = new LinkNode<ElemType1, ElemType2>; tail = head;}
//带参数的构造函数
poly_LinkList(const ElemType1 &item1, const ElemType2 &item2 ){head = new LinkNode<ElemType1, ElemType2>(item1, item2); tail = head;}
//拷贝构造函数
poly_LinkList(poly_LinkList<ElemType1, ElemType2> &List);
//析构函数
~poly_LinkList(){ListDestroy();}
//销毁链表
void ListDestroy();
//清空链表
void ListClear();
//返回链表的长度
int ListLength() const;
//判断链表是否为空表
bool ListEmpty() const;
//在首节点之前插入一个结点
bool InsFirst( ElemType1 fact, ElemType2 indi );
//获取链表头结点
LinkNode<ElemType1,ElemType2>* GetHead() { return head;}
//设置链表头指针
void SetHead(LinkNode<ElemType1,ElemType2> *p){ head = p;}
//设置链表尾指针
void SetTail(LinkNode<ElemType1,ElemType2> *p){ tail = p;}//获取链表尾结点
LinkNode<ElemType1,ElemType2>* GetTail() { return tail;}
//返回链表的第i个元素的系数值
ElemType1 GetElem_factor(int pos);
//返回链表的第i个元素的指数值
ElemType2 GetElem_indice(int pos);
//在链表的第pos个位置之前插入e元素
bool ListInsert_prior(int pos, ElemType1 fact, ElemType2 indi);
//在链表的第pos个位置之后插入e元素
bool ListInsert_next(int pos, ElemType1 fact, ElemType2 indi);
//表头插入法动态生成链表
void CreateList_Head(vector<ElemType1> &Factor, vector<ElemType2> &Indice);
//表尾插入法动态生成链表
void CreateList_Tail(vector<ElemType1> &Factor, vector<ElemType2> &Indice);
//删除链表的第pos个位置的元素
ElemType2 ListDelete(int pos);
//按序号查找,从链表的第一个结点开始,判断当前结点是否是第i个,
//若是,则返回该结点的数据域的值;否则继续后一个,直至表结束。没有第i个结点时返回空。
bool FindElem( int k, ElemType1 &fact, ElemType2 &indi);
//bool compare(ElemType a, ElemType *b);
//按值查找,即定位。从链表的第一个结点开始,判断当前结点值是否等于e。
//若是,则返回该结点的序号;否则继续后一个,直至表结束。找不到时返回0。
int SearchElem( const ElemType2 &e) const;
//返回链表给定数据元素的后继数据元素的值
bool NextElem(LinkNode<ElemType1, ElemType2> *p, ElemType1 &fact, ElemType2 &indi);
//遍历链表
bool ListTraverse() const;
};输入说明 :
第一行:加/减法选择(0:加法 1:减法)
第二行:一元多项式A的各项的系数(系数之间以空格分隔)
第三行:一元多项式A的各项的指数(指数之间以空格分隔)
第四行:一元多项式B的各项的系数(系数之间以空格分隔)
第五行:一元多项式B的各项的指数(指数之间以空格分隔)
输出说明 :
见测试数据样例
输入范例 :
0
7.1 3.2 -22.3 9 5 -8
0 1 7 8 17 100
-3.2 22 -9
1 7 18输出范例 :
7.1+3.2x-22.3x^7+9x^8+5x^17-8x^100
-3.2x+22x^7-9x^187.1-0.3x^7+9x^8+5x^17-9x^18-8x^100
2.题解
- 挖坑,注意数据输出的处理(属实是麻烦
3.代码实现
- 完整代码
#include <iostream> #include <cstring> #include <vector> #include <cmath> #include <sstream> using namespace std; //单链表的结点定义 (用于一元多项式计算) template<class ElemType1, class ElemType2> struct LinkNode { ElemType1 factor; //系数 ElemType2 indice; //指数 LinkNode<ElemType1, ElemType2> *next; LinkNode(LinkNode<ElemType1, ElemType2> *ptr = NULL) { next = ptr; //构造函数1,用于构造头结点 } LinkNode(const ElemType1 &item1, const ElemType2 &item2, LinkNode<ElemType1, ElemType2> *ptr = NULL) //构造函数2,用于构造其他结点 //函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面 { next = ptr; factor = item1; indice = item2; } ElemType1 getFactor() { return factor; //取得结点中的系数 } ElemType2 getIndice() { return indice; //取得结点中的指数 } void SetLink( LinkNode<ElemType1, ElemType2> *link ) { next = link; //修改结点的next域 } void SetFactor( ElemType1 value ) { factor = value; //修改结点的系数 } void SetIndice( ElemType2 value ) { indice = value; //修改结点的指数 } }; //带头结点的单链表(用于一元多项式计算) template<class ElemType1, class ElemType2> class poly_LinkList { private: LinkNode<ElemType1, ElemType2> *head; // 头结点 LinkNode<ElemType1, ElemType2> *tail; // 尾结点 public: //无参数的构造函数 poly_LinkList() { head = new LinkNode<ElemType1, ElemType2>; tail = head; } //带参数的构造函数 poly_LinkList(const ElemType1 &item1, const ElemType2 &item2 ) { head = new LinkNode<ElemType1, ElemType2>(item1, item2); tail = head; } //拷贝构造函数 poly_LinkList(poly_LinkList<ElemType1, ElemType2> &List); //析构函数 ~poly_LinkList() { ListDestroy(); } //销毁链表 void ListDestroy(); //清空链表 void ListClear(); //返回链表的长度 int ListLength() const; //判断链表是否为空表 bool ListEmpty() const; //在首节点之前插入一个结点 bool InsFirst( ElemType1 fact, ElemType2 indi ); //获取链表头结点 LinkNode<ElemType1,ElemType2>* GetHead() { return head; } //设置链表头指针 void SetHead(LinkNode<ElemType1,ElemType2> *p) { head = p; } //设置链表尾指针 void SetTail(LinkNode<ElemType1,ElemType2> *p) { tail = p; } //获取链表尾结点 LinkNode<ElemType1,ElemType2>* GetTail() { return tail; } //返回链表的第i个元素的系数值 ElemType1 GetElem_factor(int pos); //返回链表的第i个元素的指数值 ElemType2 GetElem_indice(int pos); //在链表的第pos个位置之前插入e元素 bool ListInsert_prior(int pos, ElemType1 fact, ElemType2 indi); //在链表的第pos个位置之后插入e元素 bool ListInsert_next(int pos, ElemType1 fact, ElemType2 indi); //表头插入法动态生成链表 void CreateList_Head(vector<ElemType1> &Factor, vector<ElemType2> &Indice); //表尾插入法动态生成链表 void CreateList_Tail(vector<ElemType1> &Factor, vector<ElemType2> &Indice); //删除链表的第pos个位置的元素 ElemType2 ListDelete(int pos); //按序号查找,从链表的第一个结点开始,判断当前结点是否是第i个, //若是,则返回该结点的数据域的值;否则继续后一个,直至表结束。没有第i个结点时返回空。 bool FindElem( int k, ElemType1 &fact, ElemType2 &indi); //bool compare(ElemType a, ElemType *b); //按值查找,即定位。从链表的第一个结点开始,判断当前结点值是否等于e。 //若是,则返回该结点的序号;否则继续后一个,直至表结束。找不到时返回0。 int SearchElem( const ElemType2 &e) const; //返回链表给定数据元素的后继数据元素的值 bool NextElem(LinkNode<ElemType1, ElemType2> *p, ElemType1 &fact, ElemType2 &indi); //遍历链表 void ListTraverse(); }; template<class T1,class T2> void poly_LinkList<T1,T2>::ListDestroy() { auto t=head; while(t) { delete head; t=t->next; } } template<class T1,class T2> void poly_LinkList<T1,T2>::ListTraverse() { int flag=0; auto it=head->next; auto t=head; for(it; it!=tail; it=t) { if(it->factor) { flag=1; if(abs(it->factor)!=1)cout<<(it->factor); if(it->factor==-1)cout<<'-'; if(it->indice) { if((it->indice)!=1) cout<<"x^"<<(it->indice); else cout<<'x'; } } t=it->next; if((t->factor)>0) cout<<'+'; } if(it->factor) { flag=1; if(abs(it->factor)!=1)cout<<(it->factor); if(it->factor==-1)cout<<'-'; if(it->indice) { if((it->indice)!=1) cout<<"x^"<<(it->indice); else cout<<'x'; } } if(!flag)cout<<0; cout<<endl; } template<class T> void f(stringstream &in,vector<T> &A) { T str; while(in>>str) A.push_back(str); } template<class T1,class T2> void poly_LinkList<T1,T2>::CreateList_Tail(vector<T1> &Factor, vector<T2> &Indice) { for(int i=0; i<Factor.size(); i++) { auto t=new LinkNode<T1,T2>(Factor[i],Indice[i]); tail->next=t; tail=t; } } template<class ElemType1,class ElemType2> void Add_Poly( poly_LinkList<ElemType1,ElemType2> &A, poly_LinkList<ElemType1,ElemType2> &B, int add_sub ) { A.ListTraverse(); B.ListTraverse(); cout<<endl; auto ta=A.GetHead()->next; auto tb=B.GetHead()->next; auto t=A.GetHead(); while(add_sub&&tb) { tb->factor=(-1)*tb->factor; tb=tb->next; } tb=B.GetHead()->next; while(ta && tb) { if(ta->indice < tb->indice) { t->next=ta; t=t->next; ta=ta->next; } else if(ta->indice > tb->indice) { t->next=tb; t=t->next; tb=tb->next; } else { double x=(ta->factor)+(tb->factor); ta->factor=x; t->next=ta; t=t->next; ta=ta->next; tb=tb->next; } } if(ta) t->next=ta; if(tb) t->next=tb; A.ListTraverse(); } int main() { int n; string f1,i1,f2,i2; vector<double> F1,F2; vector<int> I1,I2; cin>>n; getchar(); getline(cin,f1); getline(cin,i1); getline(cin,f2); getline(cin,i2); stringstream fa1(f1); stringstream in1(i1); stringstream fa2(f2); stringstream in2(i2); f(fa1,F1); f(in1,I1); f(fa2,F2); f(in2,I2); poly_LinkList<double,int> a,b; a.CreateList_Tail(F1,I1); b.CreateList_Tail(F2,I2); Add_Poly(a,b,n); return 0; }