问题描述 :
目的:使用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 &A, poly_LinkList &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;
};
题解
#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
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; }
//设置链表头指针
void SetHead(LinkNode<ElemType1, ElemType2>* p) { head = p; }
//设置链表尾指针
void SetTail(LinkNode<ElemType1, ElemType2>* p) { tail = p; }
bool push_back(ElemType1 x1, ElemType2 x2)
{
LinkNode <ElemType1, ElemType2>* p = new LinkNode<ElemType1, ElemType2>(x1, x2);
tail->next = p;
SetTail(p);
return 1;
}
poly_LinkList(ElemType1 item1[], ElemType2 item2[], int num)
{
int i = 0;
head = new LinkNode<ElemType1, ElemType2>(item1[0],item2[0]); tail = head;
for (i = 1; i < num; i++) {
push_back(item1[i], item2[i]);
}
}
//在首节点之前插入一个结点
bool InsFirst(ElemType1 fact, ElemType2 indi)
{
LinkNode <ElemType1, ElemType2>* p = new LinkNode<ElemType1, ElemType2>(fact, indi);
p->next = GetHead();
SetHead(p);
return 1;
}
//获取链表头结点
LinkNode<ElemType1, ElemType2>* GetHead() { return head; }
//获取链表尾结点
LinkNode<ElemType1, ElemType2>* GetTail() { return tail; }
//删除链表的第pos个位置的元素
ElemType2 ListDelete(int pos)
{
LinkNode <ElemType1, ElemType2>* p = GetHead();
if (pos == 0) {
p = head;
head = head->next;
if (tail == p)
tail = head;
delete p;
return 1;
}
else if (pos == 1) {
if (tail == p->next)
tail = head;
p = p->next;
head->next = head->next->next;
delete p;
return 1;
}
LinkNode <ElemType1, ElemType2>* q = p;
int pos1 = pos-1;
while (--pos)
p = p->next;
while (--pos1)
q = q->next;
if (tail == p)
tail == q;
q->next = p->next;
delete p;
return 1;
}
bool ListTraverse()
{
LinkNode <ElemType1, ElemType2>* p = GetHead();
while (p != NULL) {
if (p == GetHead()) {
if ((p->factor != 1 && p->factor != -1)||p->indice==0)
cout << p->factor;
else if (p->factor == -1)
cout << "-";
if (p->indice != 0 && p->indice != 1)
cout << "x^" << p->indice;
else if (p->indice == 1)
cout << "x";
}
else {
if (p->factor > 0 && p->factor != 1) {
cout << "+" << p->factor;
}
else if (p->factor < 0 && p->factor != -1)
cout << p->factor;
else if (p->factor == 1)
cout << "+";
else if (p->factor == -1)
cout << "-";
if (p->indice != 0 && p->indice != 1)
cout << "x^" << p->indice;
else if (p->indice == 1)
cout << "x";
}
p = p->next;
}
return 1;
}
void Add_Poly(poly_LinkList<ElemType1,ElemType2>& A, poly_LinkList<ElemType1,ElemType2>& B, int add_sub)
{
LinkNode <ElemType1, ElemType2>* p = A.GetHead();
LinkNode <ElemType1, ElemType2>* q = B.GetHead();
while (p != NULL) {
if (q != NULL) {
if (p->indice == q->indice) {
if (add_sub == 1)
p->factor += q->factor;
else
p->factor -= q->factor;
q = q->next;
B.ListDelete(0);
if (p->next == NULL)
continue;
}
else if (p->indice > q->indice) {
if (add_sub == 1)
A.InsFirst(q->getFactor(), q->getIndice());
else
A.InsFirst(-q->getFactor(), q->getIndice());
q = q->next;
B.ListDelete(0);
continue;
}
else if ((p->indice < q->indice) && (p->next != NULL) && (p->next->indice > q->indice)) {
if (add_sub == 1) {
ElemType1 v1 = q->factor; ElemType2 v2 = q->indice;
LinkNode <ElemType1, ElemType2>* v = new LinkNode<ElemType1, ElemType2>(v1, v2);
v->next = p->next; p->next = v;
q = q->next;
B.ListDelete(0);
continue;
}
else {
ElemType1 v1 = -q->factor; ElemType2 v2 = q->indice;
LinkNode <ElemType1, ElemType2>* v = new LinkNode<ElemType1, ElemType2>(v1, v2);
v->next = p->next; p->next = v;
q = q->next;
B.ListDelete(0);
continue;
}
}
else if ((p->indice < q->indice) && (p->next == NULL)) {
if (add_sub == 1)
A.push_back(q->factor, q->indice);
else
A.push_back(-q->factor, q->indice);
q = q->next;
B.ListDelete(0);
if (q != NULL)
continue;
}
}
p = p->next;
}
int num = 0;
p = A.GetHead();
while (p != NULL) {
if (p->factor == 0) {
p = p->next;
A.ListDelete(num);
continue;
}
p = p->next;
num++;
}
}
};
int main()
{
double factor1[10000] = { 0 }, factor2[10000] = { 0 };
int indice1[10000] = { 0 }, indice2[10000] = { 0 }, num1 = 0, ok = 0;
string str;
cin >> ok;
if (ok == 0) ok = 1;
else ok = 0;
cin.get();
getline(cin, str);
char ch = 0;
int i = 0; int a = 0, b = 0; double s = 0;
for (i = 0; i < str.size(); i++) {
if (str[i] != ' ') {
s = 0;
bool jk = 0, kk = 0;; int m = 0;
if (str[i] == '-') {
jk = 1;
i++;
}
while (str[i] != ' ' && str[i] != 0) {
ch = str[i];
if (ch == '.') {
kk = 1;
i++; continue;
}
s *= 10;
s += ch - '0';
if (kk == 1)
m++;
i++;
}
int sum = 1;
while (m--)
sum *= 10;
s /= sum;
if (jk == 1) s = -s;
factor1[num1] = s; num1++;
}
}
int num2 = 0;
getline(cin, str);
for (i = 0; i < str.size(); i++) {
if (str[i] != ' ') {
a = 0;
bool jk = 0;
if (str[i] == '-') {
jk = 1;
i++;
}
while (str[i] != ' ' && str[i] != 0) {
ch = str[i];
a *= 10;
a += ch - '0';
i++;
}
if (jk == 1) a = -a;
indice1[num2] = a; num2++;
}
}
int num3 = 0;
getline(cin, str);
for (i = 0; i < str.size(); i++) {
if (str[i] != ' ') {
s = 0;
bool jk = 0, kk = 0;; int m = 0;
if (str[i] == '-') {
jk = 1;
i++;
}
while (str[i] != ' ' && str[i] != 0) {
ch = str[i];
if (ch == '.') {
kk = 1;
i++; continue;
}
s *= 10;
s += ch - '0';
if (kk == 1)
m++;
i++;
}
int sum=1;
while (m--)
sum *= 10;
s /= sum;
if (jk == 1) s = -s;
factor2[num3] = s; num3++;
}
}
int num4 = 0;
getline(cin, str);
for (i = 0; i < str.size(); i++) {
if (str[i] != ' ') {
a = 0;
bool jk = 0;
if (str[i] == '-') {
jk = 1;
i++;
}
while (str[i] != ' ' && str[i] != 0) {
ch = str[i];
a *= 10;
a += ch - '0';
i++;
}
if (jk == 1) a = -a;
indice2[num4] = a; num4++;
}
}
poly_LinkList <double, int> A(factor1, indice1, num1);
poly_LinkList <double, int> B(factor2, indice2, num3);
A.ListTraverse();
cout << endl;
B.ListTraverse();
cout << endl << endl;
A.Add_Poly(A,B,ok);
if (A.GetHead() != NULL)
A.ListTraverse();
else
cout << "0";
return 0;
}