问题描述 :
目的:使用C++模板设计单链表的抽象数据类型(ADT)。并在此基础上,稍加改动,针对一元多项式建立相应的稀疏多项式ADT,使用单链表ADT的基本操作,设计并实现稀疏一元多项式的加法计算的算法设计。
内容:
(1)请参照单链表的ADT模板,设计稀疏一元多项式的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考网盘中的单链表ADT原型文件,自行设计稀疏一元多项式的ADT。)
(2)ADT的简单应用:使用该ADT设计并实现稀疏一元多项式的加法计算的算法设计。
应用1:假设2个稀疏一元多项式分别由带头结点的有序单链表A和B存储(指数项递增有序)。现要求设计一个算法,实现稀疏一元多项式的加减法计算。要求使用A和B的原存储空间,且计算后B不再单独存在。输入中的单链表的长度不得在计算算法中利用,仅作为建表使用。假定:系数的数据类型为double,指数的数据类型为int。
注意:加/减法计算后,如某一项的结果系数为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 ElemType1 &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
-8 22 -9
1 7 8
输出范例 :
7.1+3.2x-22.3x^7+9x^8+5x^17-8x^100
-8x+22x^7-9x^87.1-4.8x-0.3x^7+5x^17-8x^100
解题代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <sstream>
#include <stack>
#include <map>
#include <ctime>
#include <array>
#include <set>
#include <list>
using namespace std;
//???ADT
/* ???????? */
template <class ElemType>
struct LinkNode
{
ElemType data; //??
LinkNode<ElemType> *next; //next??
LinkNode(LinkNode<ElemType> *ptr = NULL)
{
//???????????next??
next = ptr;
}
LinkNode(const ElemType &item, LinkNode<ElemType> *ptr = NULL)
{
//?????????????????:??+next???
next = ptr;
data = item;
}
};
//????????
template <class ElemType>
class LinkList
{
private:
LinkNode<ElemType> *head; // ???
LinkNode<ElemType> *tail; // ???
void empty_push(ElemType num) //??????????
{
head = new LinkNode<ElemType>; //?????????
tail = head; //????????
head->data = num; //??
//head->next = NULL;
return;
}
bool check_P(int n) //????????:0-n
{
if (0 <= n && n < size())
return true;
return false;
}
public:
/*
int size(void)????
LinkNode<ElemType>* get_address(int i)//?????????
void have_look(void) //??
void push_back(ElemType num) //????
void insert_head(ElemType num) ????
bool insert_back(int place, ElemType num) ?????????
*/
LinkList()
{
//????????
//head = new LinkNode<ElemType>;//?????????
//tail = head;//????????
head = NULL;
tail = NULL;
}
LinkList(const ElemType &item)
{
//???????? ??????????
head = new LinkNode<ElemType>(item);
tail = head;
}
LinkList(LinkList<ElemType> &List)
{
//??????
;
}
~LinkList()
{
//????
}
LinkNode<ElemType> *get_address(int i) //?????????
{
LinkNode<ElemType> *pla = head;
while (i--)
{
pla = pla->next;
}
return pla;
}
void have_look(void)
{
LinkNode<ElemType> *p = head;
while (p->next != NULL)
{
cout << p->data;
cout << "->";
p = p->next;
}
cout << p->data << endl;
return;
}
int size(void) //finish ???????
{
int len = 0;
if (head == NULL && tail == NULL)
return 0;
LinkNode<ElemType> *p;
p = head;
while (p != NULL)
{
len++;
p = p->next;
}
return len;
}
void push_back(ElemType num)
{
if (size() == 0) //?????
{
empty_push(num);
return;
}
LinkNode<ElemType> *p = new LinkNode<ElemType>; //????
p->data = num; //??
tail->next = p; //???????next???p
tail = p; //?????p
return;
}
void insert_head(ElemType num)
{
if (size() == 0) //?????
{
empty_push(num);
return;
}
LinkNode<ElemType> *p = new LinkNode<ElemType>; //????
p->data = num; //??
p->next = head; //??
head = p;
return;
}
bool insert_back(int place, ElemType num)
{
if (size() == 0 && place == 0) //?????
{
empty_push(num);
return true;
}
if (check_P(place) == false) //???????
return false;
if (place == size() - 1) //??????
{
push_back(num);
return true;
}
LinkNode<ElemType> *p = get_address(place);
LinkNode<ElemType> *p2 = new LinkNode<ElemType>; //??
p2->data = num; //??
p2->next = p->next; //??
p->next = p2; //??
return true;
}
LinkNode<ElemType> *get_front(LinkNode<ElemType> *p) //??????????,???????????.
{
LinkNode<ElemType> *p1;
p1 = head;
while (p1->next != NULL)
{
if (p1->next == p)
return p1;
p1 = p1->next;
}
}
bool del(int i) //???????? ???,?????????(0->n-1)
{
return del_p(get_address(i));
}
bool del_p(LinkNode<ElemType> *p)
{
if (size() == 0)
return false;
if (head == tail)
{
if (p == head)
{
delete head;
head = NULL;
tail = NULL;
return true;
}
else
return false;
}
if (p == head)
{
LinkNode<ElemType> *p1 = head->next;
delete head;
head = p1;
return true;
}
if (p == tail)
{
LinkNode<ElemType> *p1 = get_front(p);
delete p;
p1->next = NULL;
tail = p1;
return true;
}
LinkNode<ElemType> *p1 = get_front(p);
p1->next = p->next;
delete p;
return true;
}
ElemType at(int i)
{
LinkNode<ElemType> *p = get_address(i);
return p->data;
}
void reverse(int m, int n) //??m->n??
{
m++, n++;
LinkNode<ElemType> *newHead = new LinkNode<ElemType>;
newHead->next = head;
LinkNode<ElemType> *p = newHead;
for (int i = 0; i < m - 1; i++)
p = p->next;
LinkNode<ElemType> *start = p->next;
LinkNode<ElemType> *t = start->next;
if (n == size())
{
tail = start;
}
for (int i = m; i < n; i++)
{
start->next = t->next;
t->next = p->next;
p->next = t;
t = start->next;
}
head = newHead->next;
return;
}
LinkList<ElemType> *get_head(void)
{
return head;
}
LinkList<ElemType> *get_tail(void)
{
return head;
}
void pick(LinkList<ElemType> &lis)
{
tail->next = lis.head;
tail = lis.tail;
return;
}
};
//LinkList<int> a;
vector<double> departString_double(string data)
{
vector<double> back_part; //output type
int i, j;
vector<string> part;
string A_part;
stringstream room;
room.str(data);
while (room >> A_part)
part.push_back(A_part);
for (i = 0; i < part.size(); i++)
{
double num_cahe;
num_cahe = atof(part[i].c_str());
back_part.push_back(num_cahe);
}
return back_part;
}
template <class ElemType>
void output(list<ElemType> &A, list<ElemType> &B)
{
bool ok = 0;
auto j = B.begin();
for (auto i = A.begin(); i != A.end(); i++)
{
if (*i == 0)
;
else if (*j == 0)
if (*i < 0)
cout << *i, ok = 1;
else if (ok)
cout << '+' << *i, ok = 1;
else
cout << *i, ok = 1;
else if (*j == 1)
if (*i < 0)
if (*i != -1)
cout << *i << "x", ok = 1;
else
cout << "-x", ok = 1;
else if (ok)
if (*i != 1)
cout << '+' << *i << "x", ok = 1;
else
cout << '+' << "x", ok = 1;
else if (*i != 1)
cout << *i << "x", ok = 1;
else
cout << "x", ok = 1;
else if (*i < 0)
if (*i != -1)
cout << *i << "x^" << *j, ok = 1;
else
cout << '-' << "x^" << *j, ok = 1;
else if (ok)
if (*i != 1)
cout << '+' << *i << "x^" << *j, ok = 1;
else
cout << '+' << "x^" << *j, ok = 1;
else if (*i != 1)
cout << *i << "x^" << *j, ok = 1;
else
cout << "x^" << *j, ok = 1;
j++;
}
if (ok == 0)
cout << 0 << endl;
cout << endl;
return;
}
int main()
{
int i, j;
vector<double> a_f, a_i;
vector<double> b_f, b_i;
string l1, l2, l3, l4;
bool oper;
cin >> oper;
cin.get();
getline(cin, l1);
getline(cin, l2);
getline(cin, l3);
getline(cin, l4);
a_f = departString_double(l1);
a_i = departString_double(l2);
b_f = departString_double(l3);
b_i = departString_double(l4);
//output(a_f);
//output(a_i);
//output(b_f);
//output(b_i);
list<double> A_f, B_f, A_i, B_i;
for (i = 0; i < a_f.size(); i++)
A_f.push_back(a_f[i]);
for (i = 0; i < a_i.size(); i++)
A_i.push_back(a_i[i]);
for (i = 0; i < b_f.size(); i++)
B_f.push_back(b_f[i]);
for (i = 0; i < b_i.size(); i++)
B_i.push_back(b_i[i]);
output(A_f, A_i);
output(B_f, B_i);
cout << endl;
auto I_1 = A_f.begin(), I_2 = A_i.begin();
auto I_3 = B_f.begin(), I_4 = B_i.begin();
list<double> ans_f, ans_i;
while (I_2 != A_i.end())
{
while (I_4 != B_i.end() && *I_4 < *I_2)
{
if (!oper)
ans_f.push_back(*I_3);
else
ans_f.push_back(-*I_3);
ans_i.push_back(*I_4);
I_3++;
I_4++;
}
if (*I_2 == *I_4)
{
if (oper)
{
ans_f.push_back(*I_1 - *I_3);
ans_i.push_back(*I_4);
}
else
{
ans_f.push_back(*I_3 + *I_1);
ans_i.push_back(*I_4);
}
I_3++;
I_4++;
}
else
{
ans_f.push_back(*I_1);
ans_i.push_back(*I_2);
}
I_1++;
I_2++;
}
while (I_4 != B_i.end())
{
if (!oper)
ans_f.push_back(*I_3);
else
ans_f.push_back(-*I_3);
ans_i.push_back(*I_4);
I_3++;
I_4++;
}
output(ans_f, ans_i);
return 0;
}