这次的题相比之前有点难,代码有点复杂,大家尽力看明白,我也会在旁边批注。
同学们不要白嫖!
7 有序链表ADT模板简单应用算法设计:一元多项式的加/减法运算
作者: 冯向阳时间限制: 1S章节: DS:线性表
截止日期: 2022-06-30 23:55:00
问题描述 :
目的:使用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^18
7.1-0.3x^7+9x^8+5x^17-9x^18-8x^100
-------------------------------------------------------------------------
Donghua University Online Judge 1.0
Copyright © 2015-2016 . All Rights Reserved.
技术支持:Turbo Email:11249242@qq.com
-------------------------------------------------------------------------
代码有点长但是 思路比较简单,请同学们耐心看完.
#include<iostream>
using namespace std;
struct student
{
double coe;//coe是coefficient的简称,coefficient中文是系数的意思
int power;//power是次方的意思
student* next = NULL;
};//每个节点的名字
void creat(student& a)
{
student* p = &a;
double j = 0;
while (cin >> j)
{
student* r = new student;
r->coe = j;
p->next = r;
p = r;
if (cin.get() == '\n')
{
break;
}
}//识别到回车 停止输入系数
int i;
p = a.next;
while (cin >> i)
{
p->power = i;
p = p->next;
if (cin.get() == '\n')//
{
break;
}//识别到回车 停止输入次方
}
}//创建一个线性表(单链表)
void display(student& a)
{
student* p = a.next;
int h = 0;
while (p != NULL)
{
if (p->coe > 0)
{
if (h != 0)
{
cout << "+";
}//若输出的开头的一个数是个正数,那就不能在前面输出+号 +号需要被省略
if (p->coe != 1)//系数不是1的时候可直接输出
{
cout << p->coe;
}
else if (p->coe == 1 && p->power == 0)//如果是1,但次方为0,直接输出数字,若次方不为0直接输出后面的x项,例如你输出1x^2是错误的 而是输出x^2
{
cout << p->coe;
}
if (p->power != 0 && p->power != 1)
{
cout << "x^";
cout << p->power;
}
else if (p->power == 1)
{
cout << 'x';
}
h++;
}
else if (p->coe < 0)
{
if (p->coe != -1)//除了-1 都可以正常输出
{
cout << p->coe;
}
else if (p->coe == -1 && p->power != 0)//若系数是-1但次方不是0的话 直接输出-号比如 -x正确 但-1x错误
{
cout << "-";
}
else if (p->coe == -1 && p->power == 0)//同理
{
cout << "-1";
}
if (p->power != 0 && p->power != 1)
{
cout << "x^";
cout << p->power;
}
else if (p->power == 1)
{
cout << 'x';
}
h++;
}
else if (p->next == NULL && p->coe == 0)
{
cout << 0;
}
p = p->next;
}
}
void merge_plus(student& a, student& b, student& c)
{
student* p = a.next;
student* q = b.next;
student* key = &c;
while (p != NULL && q != NULL)
{
if (p->power < q->power)
{
key->next = p;
key = p;
p = p->next;
}
else if (p->power > q->power)
{
key->next = q;
key = q;
q = q->next;
}
else if (p->power == q->power)
{
p->coe = p->coe + q->coe;
key->next = p;
key = p;
q = q->next;
p = p->next;
}
}
if (q != NULL)
{
key->next = q;
}
else if (p != NULL)
{
key->next = p;
}
}//plus 是加法的意思
void merge_subtract(student& a, student& b, student& c)
{
student* p = a.next;
student* q = b.next;
student* key = &c;
while (p != NULL && q != NULL)
{
if (p->power < q->power)
{
key->next = p;
key = p;
p = p->next;
}
else if (p->power > q->power)
{
key->next = q;
q->coe = -(q->coe);
key = q;
q = q->next;
}
else if (p->power == q->power)
{
p->coe = p->coe - q->coe;
key->next = p;
key = p;
q = q->next;
p = p->next;
}
}
if (q != NULL)
{
key->next = q;
}
else if (p != NULL)
{
key->next = p;
}
}//subtract是减法的意思
int main()
{
int judge;
cin >> judge;
if (judge == 0)
{
student a;
creat(a);
student b;
creat(b);
display(a);
cout << endl;
display(b);
cout << endl;
student c;
merge_plus(a, b, c);//
cout << endl;
display(c);
}
else if (judge == 1)
{
student a;
creat(a);
student b;
creat(b);
display(a);
cout << endl;
display(b);
cout << endl;
student c;
merge_subtract(a, b, c);//
cout << endl;
display(c);
}
return 0;
}