问题描述
假设2个任意长度的整数x、y分别由双向链表A和B存储,现要求设计一个算法,实现x+y。计算结果存储在链表C中。
说明:
由于A和B输出时需要从头至尾遍历,而做加法时需要从尾至头遍历,因此使用双向链表存储。
可以从长整数的低位开始拆分(4位为一组,即不超过9999的非负整数),依次存放在链表的每个结点的数据域中;头结点的数据域存放正负数标志(正数或0:1,负数:-1)。
输入说明
第一行:长整数x
第二行:长整数y
输出说明
第一行:格式化后的长整数x(从低位到高位每4位用","分开)
第二行:格式化后的长整数y(从低位到高位每4位用","分开)
第三行:空行
第四行:单链表C的遍历结果
第五行:格式化后的计算结果(从低位到高位每4位用","分开)
(输入与输出之间用一空行分隔)
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
struct node{ //num ºÍ next
int num;
struct node* next;
struct node* pre;
};
struct node* create(string s){ //采用头插法插入
struct node* head = new node;
head->next = NULL;
head->pre = NULL;
int l;
if(s[s.length() - 1] == '-'){
l = s.length()-1;
head->num = -1;
}
else{
l = s.length();
head->num = 1;
}
int f = 0;
int num = 0;
for(int i = 0;i < l;i++){
num += (int)(s[i]-'0') * (pow(10,f)+0.1);
f++;
if(f == 4 || i == l-1){ //当读取4个数时重置
//cout<<"*****"<<num<<"******"<<endl;
struct node* p = new node;
p->num = num;
struct node* q = head->next;
head->next = p;
p->pre = head;
p->next = q;
if(q)
q->pre = p;
f = 0;
num = 0;
}
} //for
return head;
}
void display(struct node* num){
if(num->next){
if(num->num == -1)
cout<<'-';
struct node* p = num->next;
cout<<p->num;
p = p->next;
while(p){
if(p == num->next)
printf("%04d",p->num);
//cout<<abs(p->num);
else
printf(",%04d",p->num);
p = p->next;
}
}
else
cout<<0;
}
struct node* add(struct node* num1,struct node* num2){
struct node* head = new node;
head->next = NULL;
head->pre = NULL;
//cout<<"1";
struct node* p = num1;
struct node* q = num2;
//cout<<"2";
while(p->next)
p = p->next;
//cout<<"3";
while(q->next)
q = q->next;
//cout<<"4";
while(p != num1 && q != num2){ //从尾部到头部进行加遍历
struct node* t = new node;
//cout<<"111";
struct node* o = head->next;
//cout<<"2222";
t->num = num1->num*p->num + num2->num*q->num;
head->next = t;
t->pre = head;
t->next = o;
if(o)
o->pre = t;
p = p->pre;
q = q->pre;
}
while(p != num1){ //类似于合并有序表,对没有运算的结点采用头部插入的方法
struct node* t = new node;
struct node* o = head->next;
t->num = num1->num * p->num;
head->next = t;
t->pre = head;
t->next = o;
if(o)
o->pre = t;
p = p->pre;
}
while(q != num2){
struct node* t = new node;
struct node* o = head->next;
t->num = num2->num * q->num;
head->next = t;
t->pre = head;
t->next = o;
if(o)
o->pre = t;
q = q->pre;
}
//display(head);
if(head->next->num > 0) //判断最后的取值是正是负
head->num = 1;
else
head->num = -1;
p = head;
while(p->next)
p = p->next;
q = p;
while(p != head){ //对结果进行处理
if(p->num * head->num < 0){ //正数借位减一,负数借位加1
if(head->num > 0){
p->num += 10000;
p->pre->num -= 1;
}
else{
p->num -= 10000;
p->pre->num += 1;
}
}
p = p->pre;
}
//cout<<5;
p = head->next;
while(p){
p->num = abs(p->num);
p = p->next;
}
//cout<<6<<endl;
while(q != head->next){ //进行进位处理
if(q->num >= 10000){
q->num -= 10000;
q->pre->num += 1;
}
q = q->pre;
}
if(q && q->num >= 10000){
struct node* t = new node;
t->next = q;
q->pre = t;
head->next = t;
t->pre = head;
t->num = q->num / 10000;
q->num = q->num % 10000;
}
p = head->next; //当前边出现0时删除该结点
while(p && p->num == 0){
p->pre->next = p->next;
if(p->next)
p->next->pre = p->pre;
p = p->next;
}
return head;
};
void display_2(struct node* head){
if(head->next){
struct node* p = head->next;
cout<<p->num;
p = p->next;
while(p){
printf("->%04d",p->num);
p = p->next;
}
cout<<endl;
}
else
cout<<0<<endl;
}
/*
测试用例
-109921335327
74111423
-1099 5278 -3904
- 1098 4722 3904
*/
int main(){
//cout<<8*pow(10,0);
string s1,s2;
struct node *num1,*num2,*c;
cin>>s1;
cin>>s2;
reverse(s1.begin(),s1.end());
num1 = create(s1);
display(num1);
cout<<endl;
reverse(s2.begin(),s2.end());
num2 = create(s2);
display(num2);
cout<<endl<<endl;
c = add(num1,num2);
display_2(c);
display(c);
return 0;
}