问题描述 :
目的:使用C++模板设计单链表的抽象数据类型(ADT)。并在此基础上,使用单链表ADT的基本操作,设计并实现单链表的应用算法设计。
内容:(1)请使用模板设计单链表的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考网盘中的ADT原型文件。)
(2)ADT的应用:使用该ADT设计并实现单链表应用场合的算法设计。
应用:假设2个任意长度的整数x、y分别由带头结点的单链表A和B存储,现要求设计一个算法,实现任意长的整数进行加法运算,运算结果存储在字符串中。
参考函数原型:
template<class ElemType>
void Long_Int_Add( LinkList<ElemType> &A, LinkList<ElemType> &B, string &result, const int &len_A, const int &len_B );
辅助函数原型:
(1)从长整数的低位开始拆分(4位为一组,即不超过9999的非负整数),依次存放在单链表的每个结点的数据域中;头结点的数据域存放正负数标志(正数或0:1,负数:-1)。
template<class ElemType>
void Input_Int_Division( LinkList<ElemType> &L, string &str, int &length ); (length:长整数分割后的block数,恰为存储用单链表的长度)
(2)计算结果中间位格式控制
string Int_String( int result );
(3)两个长整数的绝对值大小比较(x>y 返回值为1;x<y 返回值为2;x=y 返回值为0;)
template<class ElemType>
int Two_LongNum_Compare( LinkList<ElemType> &A, LinkList<ElemType> &B, const int &len_A, const int &len_B );
(4)单链表ADT基本操作:单链表的逆置(实际计算时,鉴于单链表的顺序查找的特性,存储在单链表中的长整数需逆置,由原始的高位到低位排列,逆置为低位到高位降序排列。)
template<class ElemType>
void LinkList<ElemType>::ListReverse();
(5)单链表格式遍历:按照长整数的格式(4位为一组,组与组之间用,分隔)
template<class ElemType>
bool ListTraverse(LinkList<ElemType> &LInt)
输入说明 :
第一行:长整数x
第二行:长整数y
输出说明 :
第一行:格式化后的长整数x(从低位到高位每4位用","分开)
第二行:格式化后的长整数y(从低位到高位每4位用","分开)
第三行:空行
第四行:格式化后的计算结果(从低位到高位每4位用","分开)
(输入与输出之间用一空行分隔)
输入范例 :
-534564675768465476586798709880985345646757684654765867987098809853456467576846547658679870988098534564675768465476586798709880985345646757684654765867987098809853456467576846547658679870988098534564675768465476586798709880985345646757684654765867987098809853456467576846547658679870988098534564675768465476586798709880985345646757684654765867987098809853456467576846547658679870988098
435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679
输出范例 :
-5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098
4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679
-5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,2111,1392,9797,7801,8855,1455,0549,9647,0788,1412,0279,2801,6941,9155,2454,7797,0769,0089,0298,3283,1941,7242,0154,9701,8919,0069,8975,3302,2423,2241,8241,7402,0823,8219,8956,1979,2442,2723,3241,5488,8524,0124,7106,1960,1119,2742,3723,0488,6610,7824,9011,0110,1100,1419,3742,0970,1610,5911,6711,2014,9250,1400,2419
参考代码:
#include<bits/stdc++.h>
using namespace std;
/* 单链表的结点定义 */
template<class ElemType>
struct Node {
ElemType data;
Node<ElemType> *next;
Node(Node<ElemType> *ptr = NULL) {
next = ptr; //构造函数1,用于构Node造头结点
}
Node(const ElemType &item, Node<ElemType> *ptr = NULL) //构造函数2,用于构造其他结点
//函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
{
next = ptr;
data = item;
}
};
//带头结点的单链表
template<class ElemType>
class LinkList {
private:
Node<ElemType> *head; // 头指针
Node<ElemType> *tail; // 尾指针
public:
//重载函数:赋值
LinkList<ElemType> operator=(LinkList<ElemType> &List);
//无参数的构造函数
LinkList() {
head = new Node<ElemType>;
tail = head;
}
//带参数的构造函数
LinkList(const ElemType &item) {
head = new Node<ElemType>;
head->next = tail = new Node<ElemType>(item);
}
//析构函数
~LinkList() {
Destroy();
}
//拷贝构造函数
LinkList(const LinkList<ElemType> &List);
//销毁链表中所有结点,释放内存
void Destroy();
//返回链表的长度
int GetLength() const;
//用e返回链表的第i个元素数据
ElemType GetElem(int i);
//用e返回链表pos位置的元素数据
void ListInsert(int index, ElemType &e);
//遍历
bool ListTraverse() const;
};
//重载函数:赋值
template<class ElemType>
LinkList<ElemType> LinkList<ElemType>::operator=(LinkList<ElemType> &List) {
head = new Node<ElemType>;
tail = head;
Node<ElemType> *r; //r为指向尾结点的指针
r = tail;
Node<ElemType> *p = List.head->next; //p为指向待插入结点的指针
while (p) {
Node<ElemType> *q = new Node<ElemType>;
q->data = p->data;
r->next = q;
r = q;
p = p->next;
}
r->next = NULL;
tail = r;
return *this;
}
template<class ElemType>
int LinkList<ElemType>::GetLength() const {
//返回链表的长度
int length = 0;
Node<ElemType> *p;
p = head->next;
while (p) {
++length;
p = p->next;
}
return length;
}
template<class ElemType>
ElemType LinkList<ElemType>::GetElem(int i) {
//由于本函数隐含了一个循环,因此会使得程序的时间复杂度增大n倍,因此不建议实现本方法
Node<ElemType> *p;
p = head->next;
int j = 1; //初始化,p指向第一个结点,j为计数器
while (j < i && p) { //顺链域向后扫描,直到p指向第i个元素或p为空
p = p->next; //p指向下一个结点
++j; //计数器j相应加1
}
return p->data; //取第i个结点的数据域
}
template<class ElemType>
void LinkList<ElemType>::ListInsert(int i, ElemType &e) {
//在带头结点的单链表L中第i个位置插入值为e的新结点
int j;
Node<ElemType> *p, *s;
p = head;
j = 0;
while (p && j < i - 1) {
p = p->next;
++j;
}//查找第i-1个结点,p指向该结点
s = new Node<ElemType>; //生成新结点*s
s->data = e; //将结点*s的数据域置为e
s->next = p->next; //将结点*s的指针域指向结点ai
p->next = s; //将结点*p的指针域指向结点*s
if (p == tail) tail = s; //在最后插入结点,需要修改尾指针
} //ListInsert
template<class ElemType>
bool LinkList<ElemType>::ListTraverse() const {
//遍历链表
Node<ElemType> *p;
int sum = 0;
p = head->next;
if(p->next!=NULL) cout<<p->data<<",";
else cout<<p->data;
p=p->next;
while (p) {
if (p->next != NULL&& p->data >= 0) cout <<setw(4)<<setfill('0')<< p->data << ",";
else if (p->next != NULL&&p->data < 0) cout <<setw(4)<<setfill('0')<< -p->data<<",";
else if(p->next == NULL&&p->data < 0) cout<<setw(4)<<setfill('0')<<-p->data;
else if(p->next == NULL&&p->data >= 0) cout<<setw(4)<<setfill('0')<<p->data;
p = p->next;
} // while
cout << endl;
return true;
}
template<class ElemType>
void LinkList<ElemType>::Destroy() {
//销毁以head为头指针的单链表,释放链表中所有结点空间
Node<ElemType> *p;
while (head) {
p = head;
head = head->next;
delete p;
}
head = NULL;
}
LinkList<int> x1(string a) {
int sum = 0, num = 1, f = 0, h = 0, i = 0;
LinkList<int> z;
if (a[0] == '-') {
i++;
f = 1;
if((a.size()-1)%4!=0) h=4-(a.size()-1)%4;
}
else if(a.size()%4!=0) h=4-a.size()%4;
for (; i < a.size(); i++) {
if (h == 4) {
if (f == 1) sum = -sum;
z.ListInsert(num++, sum);
sum = 0;
h = 0;
i--;
} else {
sum = sum * 10 + a[i] - '0';
h++;
}
}
if (f == 1) sum = -sum;
z.ListInsert(num, sum);
return z;
}
template<class ElemType>
void Long_Int_Add(LinkList<ElemType> a, LinkList<ElemType> b) {
a.ListTraverse();
b.ListTraverse();
cout << endl;
int t[10000] = {0},e2;
string s;
int d = min(a.GetLength(), b.GetLength()), e = max(a.GetLength(), b.GetLength()), num;
if (a.GetElem(1) < 0 && a.GetLength() > b.GetLength() || b.GetElem(1) < 0 && b.GetLength() > a.GetLength() ) t[0] = 1;
else if(a.GetLength()==b.GetLength()){
for(int i=1;i<=a.GetLength();i++){
if((a.GetElem(i)+b.GetElem(i))<0){
t[0]=1;
break;
}
}
}
e2=e;
if ((a.GetElem(1) < 0 && b.GetElem(1) > 0 || a.GetElem(1) > 0 && b.GetElem(1) < 0) &&t[0]==1){
for (int i = 1; i <= d; i++) {
num = a.GetElem(a.GetLength() + 1 - i) + b.GetElem(b.GetLength() + 1 - i);
if (num > 0) {
t[i + 1]--;
t[i] += 10000 - num;
} else t[i] += -num;
if (t[i] == -1) {
t[i] = 9999;
t[i + 1]--;
}
}
for (int i = d+1; i <=e; i++) {
if (e == a.GetLength()) num = a.GetElem(a.GetLength() + 1 - i);
else num = b.GetElem(b.GetLength() + 1 - i);
if (num < 0) num = -num;
t[i] += num;
}
}
else if ((a.GetElem(1) < 0 && b.GetElem(1) > 0 || a.GetElem(1) > 0 && b.GetElem(1) < 0) &&t[0]==0){
for (int i = 1; i <= d; i++) {
num = a.GetElem(a.GetLength() + 1 - i) + b.GetElem(b.GetLength() + 1 - i);
if (num < 0) {
t[i + 1]--;
t[i] += 10000 + num;
} else t[i] += num;
if (t[i] == -1) {
t[i] = 9999;
t[i + 1]--;
}
}
for (int i = d+1; i <=e; i++) {
if (e == a.GetLength()) num = a.GetElem(a.GetLength() + 1 - i);
else num = b.GetElem(b.GetLength() + 1 - i);
if (num < 0) num = -num;
t[i] += num;
}
}else {
for (int i = 1; i <= d; i++) {
num = a.GetElem(a.GetLength() + 1 - i) + b.GetElem(b.GetLength() + 1 - i);
if (num < 0) num = -num;
t[i]+=num;
if (t[i] >= 10000) {
t[i] = t[i]- 10000;
t[i + 1]++;
if(i==d&&d==e) e2++;
}
}
for (int i = d+1; i <=e; i++) {
if (e == a.GetLength()) num = a.GetElem(a.GetLength() + 1 - i);
else num = b.GetElem(b.GetLength() + 1 - i);
if (num < 0) num = -num;
t[i] += num;
}
}
for(int i=e2;i>=1;i--){
if(t[i]==0) e2--;
else break;
}
if (t[0] == 1) cout << "-";
if(e2!=1&&e2!=0) cout<<t[e2]<<",";
else cout<<t[e2];
for (int i = e2-1; i >1; i--) {
cout << setw(4)<<setfill('0')<<t[i] << ",";
}
if(e2!=1&&e2!=0)cout <<setw(4)<<setfill('0')<< t[1];
}
int main() {
int n;
string s1, s2;
getline(cin, s1);
getline(cin, s2);
Long_Int_Add(x1(s1), x1(s2));
}