单链表ADT模板应用算法设计:长整数加法运算(使用单链表存储计算结果)

时间限制: 1S类别: DS:线性表->线性表应用

题目描述:

输入范例:

-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

这里利用了几个关键函数:链表的逆置 比较两个链表的绝对值大小 链表的相加 输出链表

我的题解:

//DHUOJ 单链表ADT模板应用算法设计:长整数加法运算(使用单链表存储计算结果)
#include<iostream>
#include<cstring>using namespace std;
template<class ElemType>
struct Node
{
ElemType data;
Node<ElemType>* next;
//构造函数1 用于node构造头结点
Node(Node<ElemType>* ptr = NULL)
{
next = ptr;
}
//构造函数2 用于构造其他结点
Node(const ElemType& item, Node<ElemType>* ptr = NULL)
{
next = ptr;
data = item;
} public:
ElemType getdata()
{
return data;
}
Node<ElemType>* getnext()
{
return next;
}
void set_next(Node<ElemType>* p)
{
this->next = p;
}
void set_date(ElemType num)
{
this->data = num;
}
};
template<class ElemType>
class LinkList {
private:
Node<ElemType>* head;//头指针
Node<ElemType>* tail;//尾指针 public:
//无参构造函数
LinkList()
{
head = new Node<ElemType>;
head->next = NULL;
tail = head->next;//头尾指针指向同一个内存
}
//有参构造
LinkList(const ElemType& item)
{
head = new Node<ElemType>;
tail = new Node<ElemType>;
head->next = tail = new Node<ElemType>(item);//有参构造node
}
void display()
{ //避免出现以下情况 所以我们先判断是不是就一个单0
if(head->getnext()->getdata()==0&&head->getnext()->getnext()==NULL)
{
cout<<"0";
return ;
}
if (head->getdata() == -1)
cout << "-";//如果是0就不能输出负号
//其实这样写也有问题 如果-0000 0005的就无法判断 所以我们上面解决了单0的情况
Node<ElemType>* q = head->next;
bool zeroflag = 0;
bool firstflag = 0;
//0要先特判 避免出现0 0000 0000的情况 也不行 会出现0 0000 0005 的情况无法输出
while (q->next)
{
if (q->getdata() == 0 && !zeroflag)
{
q = q->next;
continue;
}
else if(q->getdata()!=0&&!zeroflag)
{
zeroflag = 1; }
if (!firstflag)
{
cout << abs(q->data) << ",";
firstflag = 1;
}
else
printf("%04d,", abs(q->data));
q = q->next; }
if (q == head->next)//只有一位特判
cout << abs(q->data);
else
{
if (!firstflag)
{
cout << abs(q->data); }
else
{
if (!zeroflag)
{
cout << abs(q->data); }
else
{
printf("%04d", abs(q->data));
} } } cout << endl;
}
int size()
{
if (head->next == NULL)
return 0;
int len = 0;
Node<ElemType>* q;
q = head->next;
while (q)
{
len++;
q = q->next;
}
return len;
}
void push_back(ElemType x)
{
Node<ElemType>* q = new Node<ElemType>;//新建结点
q->data = x;
q->next = NULL;
if (size() == 0)
{
head->next = q; }
else
{
tail->next = q; }
tail = q; }
Node<ElemType>* get_front(Node<ElemType>* p)
{//获取一个指针的上一个,头指针和非法指针会报错.
Node<ElemType>* q;
q = head->next;
while (q->next != NULL)
{
if (q->next == p)
return q;
q = q->next;
}
}
Node<ElemType>* get_next(Node<ElemType>* p)
{
return p->next;
}
Node<ElemType>* get_address(int i)//获取指定下标的地址
{
Node<ElemType>* q;
q = head->next;
while (i--)
q = q->next;
return q;
}
ElemType at(int i)
{
Node<ElemType>* q = get_address(i);
return q->data;
}
bool del_p(Node<ElemType>* p)//传入一个指针 删除
{
if (size() == 0)
return false;
if (tail->next == NULL)//如果只有一个元素
{
if (p == tail)//如果这个指针是那个唯一的指针
{
delete tail;
tail = NULL;
return true;
}
else
return false;//如果不是 }
if (p == tail)//如果删除的是尾指针
{
Node<ElemType>* q = get_front(p);
q->next = NULL;
tail = q;
delete p;
return true;
}
//其他的
Node<ElemType>* q = get_front(p);
q->next = p->next;
delete p;
return true; }
bool del(int i)//删除指定位置的元素
{
return del_p(get_address(i));
}
Node<ElemType>* get_head()
{
return head;
}
Node<ElemType>* get_tail()
{
return tail;
}
void set_head(Node<ElemType>* p)
{ head = p;
}
void set_tail(Node<ElemType>* p)
{
tail = p;
}
void ListReverse()
{
Node<ElemType>* a, * b, * temp;
a = head->getnext();
ElemType datas = head->getdata();
temp = NULL;
b = NULL;
bool flag = 0;//设置尾指针的标志
while (a)
{
b = a;
a = a->getnext();
b->set_next(temp);
if (!flag)
{
tail = b;
flag = 1;
}
temp = b;
}
Node<ElemType>* newhead = new Node<ElemType>;
newhead->set_next(b);
newhead->set_date(datas);
head = newhead; }
}; //从长整数的低位开始拆分(4位为一组,即不超过9999的非负整数),依次存放在单链表的每个结点的数据域中;
//头结点的数据域存放正负数标志(正数或0:1,负数:-1)。
template<class ElemType>
void Input_Int_Division(LinkList<ElemType>& L, string& str, int& length)
{
Node<ElemType>* head = L.get_head();
bool zhengfu_flag = 0;//记录正负的flag
int l = str.length();
if (str[0] == '-')//先特判正负数
{ zhengfu_flag = 1;
head->set_date(-1); }
else
{
head->set_date(1);
}
int i = 0;
if (zhengfu_flag)
i = 1;
int t0 = l % 4;
if (t0 == 0)
t0 = 4;
int t = 0;//记录位数
int num = 0;//存四位数
bool changeflag = 0;//判断标志 判断是否有进行第一次
for (; i < t0; ++i)
{
num = num * 10 + (str[i] - '0');
changeflag = 1;
}
if (changeflag)
{
length++;//记录长度
L.push_back(num);
num = 0;
} for (; i < str.length(); ++i)
{ num = num * 10 + (str[i] - '0');
t++;
if (t == 4)
{
length++;//记录长度
L.push_back(num);
t = 0;
num = 0;
}
}
//L.display();
}
//两个长整数的 绝对值 大小比较
//(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)
{
Node<ElemType>* head1 = A.get_head();
Node<ElemType>* head2 = B.get_head(); //正数的情况 先看长度
if (len_A > len_B)
{
return 1;
}
else if (len_A < len_B)
{
return 2;
}
else if (len_A == len_B)
{
Node<ElemType>* a, * b;
a = head1->getnext();
b = head2->getnext();
while (a)
{
if (a->getdata() > b->getdata())
return 1;
else if (a->getdata() < b->getdata())
return 2;
else
a = a->getnext(), b = b->getnext();
}
return 0;
} }
template<class ElemType>
void swaps(LinkList<ElemType>& a, LinkList<ElemType>& b)
{
LinkList<ElemType>temp = a;
a = b;
b = temp;
}
template<class ElemType>
void Listadds(LinkList<ElemType>& a, LinkList<ElemType>& b, int& la, int& lb)
{
Node<ElemType>* x, * y; int ans = 0;
if (la < lb)
{
//swap一下两个
swaps(a, b);
int temp = la;
la = lb;
lb = temp;
}
x = a.get_head()->getnext();
y = b.get_head()->getnext();//两个指针的创建必须放在 交换判断之后
int m = a.get_head()->getdata();//m n 存储符号
int n = b.get_head()->getdata();//存储符号也必须放在交换判断之后 //第一步 判断结果的最高位//!必须再加法前进行 !!因为a会随着加法而改变 引用传递
bool flag = 0;//标记元素
int comp = Two_LongNum_Compare(a, b, la, lb); while (y)//先把每一位结点的数值加起来
{
ans = x->getdata() * m + y->getdata() * n;
x->set_date(ans);
x = x->getnext();
y = y->getnext();
}
//把长的位都化成同号的 不然接下来进位会出问题
while (x)
{
x->set_date(x->getdata() * m);
x = x->getnext();
}
//再做进位处理 if (comp == 1)
{
flag = 1;
}
//第二步 开始逐位遍历
x = a.get_head()->getnext();
int zheng_fu = 0;//判断正负的符号
if (flag)
zheng_fu = a.get_head()->getdata();
else
zheng_fu = b.get_head()->getdata();
if (zheng_fu > 0)//分正负两种情况 先看是正的
{
a.get_head()->set_date(1);//定最高位符号
while (x->getnext())//最后一个结点先不遍历 最后单独讨论
{
if (x->getdata() > 9999)
{
x->set_date(x->getdata() - 10000);
x->getnext()->set_date(x->getnext()->getdata() + 1);
//下一位就加一
}
else if (x->getdata() < 0)
{
x->set_date(x->getdata() + 10000);
x->getnext()->set_date(x->getnext()->getdata() - 1);
}
x = x->getnext();
}
//讨论最后一位 是否要进位
if (x->getdata() > 9999)
{
x->set_date(x->getdata() - 10000);
a.push_back(1);
}
}
else //讨论负数的情况
{
a.get_head()->set_date(-1);//定最高位符号
while (x->getnext())//最后一个结点先不遍历 最后单独讨论
{
if (x->getdata() < -9999)
{
x->set_date(x->getdata() + 10000);
x->getnext()->set_date(x->getnext()->getdata() - 1);
//下一位就加一
}
else if (x->getdata() > 0)
{
x->set_date(x->getdata() - 10000);
x->getnext()->set_date(x->getnext()->getdata() + 1);
}
x = x->getnext();
}
//讨论最后一位 是否要进位
if (x->getdata() < -9999)
{
x->set_date(x->getdata() + 10000);
a.push_back(1);
}
}
} int main()
{
LinkList<int>head1, head2;
string str1, str2;
getline(cin, str1);
getline(cin, str2);
int la = str1.length();
int lb = str2.length();
if (str1[0] == '-')
la -= 1;
if (str2[0] == '-')
lb -= 1;
int length1 = 0;
int length2 = 0;
Input_Int_Division(head1, str1, length1);
Input_Int_Division(head2, str2, length2);
head1.display();
head2.display();
cout << endl;
head1.ListReverse();
head2.ListReverse();
Listadds(head1, head2, la, lb);
head1.ListReverse();
head1.display();
//swaps(head1, head2);
//head1.display();
//head2.display();
//cout << endl;
//int comp = Two_LongNum_Compare(head1, head2, length1, length2);
//cout << comp;
//cout << length<<endl;
//head.ListReverse();
//head.display(); return 0; }

最新文章

  1. Uploadify 结合 Web API 2 上传问题
  2. iOS平台UDID方案比较
  3. bzoj2500: 幸福的道路(树形dp+单调队列)
  4. JavaScript中的CSS属性对照表
  5. 删除项目中的.svn文件
  6. C#:MapControl基本操作代码整理
  7. 操刀 requirejs,自己动手写一个
  8. POJ 2689
  9. TFTPD32, 3CDaemon, FlashFxp
  10. yum 安装 依赖报错
  11. js加载优化三
  12. linux中vi的基本操作
  13. Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵
  14. hdoj1003 DP
  15. request使用代理
  16. JavaScript中按键事件的e.keyCode || e.which || e.charCode
  17. 【BZOJ4800】[CEOI2015 Day2]世界冰球锦标赛 (折半搜索)
  18. Hadoop Yarn REST API未授权漏洞利用挖矿分析
  19. Golang 字符串转URLCode
  20. Linux在本地使用yum安装软件

热门文章

  1. WPF中常用控件(TreeView, ComboBox, DataGrid, ListView)使用MVVM模式绑定的demo
  2. Windows Server 2012 R2通过命令行重置网络环境
  3. JZ-062-二叉查找树的第 K 个结点
  4. 『现学现忘』Docker基础 — 10、Docker的安装
  5. 5. 堪比JMeter的.Net压测工具 - Crank 实战篇 - 接口以及场景压测
  6. 通过IMM With Remote Console为服务器安装操作系统
  7. rodert教你学FFmpeg实战这一篇就够了
  8. Python 基于 selenium 实现不同商城的商品价格差异分析系统
  9. Spring-MyBatis的配置文件
  10. 说说如何安装 Openfire