長整數加法運算/大數運算
問題描述:
假設2個任意長度的整數x、y分別由雙向鏈表A和B存儲,現要求設計一個算法,實現x+y。計算結果存儲在鏈表C中。
說明:
由於A和B輸出時需要從頭至尾遍歷,而做加法時需要從尾至頭遍歷,因此使用雙向鏈表存儲。
可以從長整數的低位開始拆分(4位爲一組,即不超過9999的非負整數),依次存放在鏈表的每個結點的數據域中;頭結點的數據域存放正負數標誌(正數或0:1,負數:-1)。
輸入說明:
第一行:長整數x
第二行:長整數y
輸出說明:
第一行:格式化後的長整數x(從低位到高位每4位用",“分開)
第二行:格式化後的長整數y(從低位到高位每4位用”,“分開)
第三行:空行
第四行:單鏈表C的遍歷結果
第五行:格式化後的計算結果(從低位到高位每4位用”,"分開)
(輸入與輸出之間用一空行分隔)
輸入:
-53456467576846547658679870988098
435643754856985679
輸出:
-5345,6467,5768,4654,7658,6798,7098,8098
43,5643,7548,5698,5679
5345->6467->5768->4611->2014->9250->1400->2419
-5345,6467,5768,4611,2014,9250,1400,2419
模擬題需要一個具體的步驟,使得思路清晰
- 首先是將所給的字符串轉化爲鏈表,這個步驟相對較爲簡單,每四位一取就可以了。
- 構建好每個鏈表後就可以進行運算了,這個時候就要考慮兩個數做的是加法還是減法運算。若進行加法運算,就直接進行,這裏所用到的思想類似於歸併排序。做加法運算時,進位位要注意最後結果如果比原鏈表長,則需要再添加。(例如 9999+1=10000)
- 做減法的時候,首先要進行比較絕對值的大小,通常運算都是大數減去小數,運算的時候較爲方便。同樣對借位位的考慮需要仔細。
- 最後就是輸出,輸出的時候需要考慮中間有的數據爲0,需要補0輸出。首部爲0,則不輸出等。
AC代碼:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<iomanip>
using namespace std;
struct num
{
int data;
num *next, *pre;
};
num *creatNum(string s)
{
num *head=new num;
num *p=head;
if(s[0]=='-')
head->data=-1;
else
head->data=1;
//cout<<head->data<<endl;
if(head->data==-1){
int count=(s.length()-1)%4;
//cout<<count<<endl;
if(count==0){
count=3;
int number=0;
for(int i=1; i<s.length(); i++){
number=number*10+s[i]-'0';
if(count==0){
num* temp=new num;
temp->data=number;
temp->pre=p;
p->next=temp;
p=p->next;
count=4;
number=0;
}
count--;
}
}
else{
count--;
int number=0;
for(int i=1; i<s.length(); i++){
number=number*10+s[i]-'0';
if(count==0){
num* temp=new num;
temp->data=number;
temp->pre=p;
p->next=temp;
p=p->next;
count=4;
number=0;
}
count--;
}
}
}
else{
int count=s.length()%4;
if(count==0){
count=3;
int number=0;
for(int i=0; i<s.length(); i++){
number=number*10+s[i]-'0';
if(count==0){
num* temp=new num;
temp->data=number;
temp->pre=p;
p->next=temp;
p=p->next;
count=4;
number=0;
}
count--;
}
}
else{
count--;
int number=0;
for(int i=0; i<s.length(); i++){
number=number*10+s[i]-'0';
if(count==0){
num* temp=new num;
temp->data=number;
temp->pre=p;
p->next=temp;
p=p->next;
count=4;
number=0;
}
count--;
}
}
}
p->next=head;
head->pre=p;
return head;
}
void display(num* head)
{
num* p = head->next;
while (p!=head && p->data == 0)p = p->next;
if (p==head) { cout << 0 << endl; return; }
if (p!=head)
{
cout << p->data;
p = p->next;
}
while (p!=head)
{
cout << "->";
cout << setw(4) << setfill('0') << p->data;
p = p->next;
}
cout << endl;
}
void my_print(num* head)
{
num* p = head->next;
while (p!=head && p->data == 0)p = p->next;
if (p==head) { cout << 0 << endl; return; }
if (head->data == -1)cout << "-";
if (p!=head)
{
cout << p->data;
p = p->next;
}
while (p!=head)
{
cout << ",";
cout << setw(4) << setfill('0') << p->data;
p = p->next;
}
cout << endl;
}
num *add(num* A, num *B)
{
num *head=new num;
head->data=A->data;
head->next=head;
head->pre=head;
num *pa=A->pre, *pb=B->pre;
int carry=0;
while(pa!=A&&pb!=B){
num *temp=new num;
temp->data=(pa->data+pb->data+carry)%10000;
carry=(pa->data+pb->data+carry)/10000;
pa=pa->pre;
pb=pb->pre;
temp->next=head->next;
temp->pre=head;
head->next->pre=temp;
head->next=temp;
}
while(pa!=A){
num *temp=new num;
temp->data=(pa->data+carry)%10000;
carry=(pa->data+carry)/10000;
pa=pa->pre;
temp->next=head->next;
temp->pre=head;
head->next->pre=temp;
head->next=temp;
}
while(pb!=B){
num *temp=new num;
temp->data=(pb->data+carry)%10000;
carry=(pb->data+carry)/10000;
pb=pb->pre;
temp->next=head->next;
temp->pre=head;
head->next->pre=temp;
head->next=temp;
}
if(carry==1){
num *temp=new num;
temp->data=1;
temp->next=head->next;
temp->pre=head;
head->next->pre=temp;
head->next=temp;
}
return head;
}
int judge(string s1, string s2)
{
if(s1[0]=='-'){
if(s1.length()-1>s2.length())
return 1;
else if(s1.length()-1<s2.length())
return -1;
else{
bool flag=false;
for(int i=0; i<s2.length(); i++){
if(s1[i+1]>s2[i])
return 1;
else if(s1[i+1]<s2[i])
return -1;
}
if(flag)
return 0;
}
}
else{
if(s1.length()>s2.length()-1)
return 1;
else if(s1.length()<s2.length()-1)
return -1;
else{
bool flag=false;
for(int i=0; i<s1.length(); i++){
if(s1[i]>s2[i+1])
return 1;
else if(s1[i]<s2[i+1])
return -1;
}
if(flag)
return 0;
}
}
}
num *sub(num *A, num *B)
{
num *head=new num;
head->data=A->data;
head->next=head;
head->pre=head;
num *pa=A->pre, *pb=B->pre;
int carry=0;
while(pa!=A&&pb!=B){
num *temp=new num;
if(pa->data-carry<pb->data){
temp->data=(10000+pa->data-carry-pb->data)%10000;
carry=1;
}
else{
temp->data=(pa->data-carry-pb->data)%10000;
carry=0;
}
pa=pa->pre;
pb=pb->pre;
temp->next=head->next;
temp->pre=head;
head->next->pre=temp;
head->next=temp;
}
while(pa!=A){
num *temp=new num;
if(pa->data-carry<0){
temp->data=(10000+pa->data-carry)%10000;
carry=1;
}
else{
temp->data=(pa->data-carry)%10000;
carry=0;
}
pa=pa->pre;
temp->next=head->next;
temp->pre=head;
head->next->pre=temp;
head->next=temp;
}
return head;
}
int main()
{
string s1, s2;
cin>>s1>>s2;
num *A=creatNum(s1);
num *B=creatNum(s2);
//cout<<A->next->data;
my_print(A);
my_print(B);
cout<<endl;
//判斷加減運算
num *res=NULL;
if(A->data==B->data){
res=add(A, B);
}
else{
int flag=judge(s1, s2);
if(flag==0){
res=sub(A, B);
res->data=0;
}
else if(flag==1)
res=sub(A, B);
else
res=sub(B, A);
}
display(res);
my_print(res);
return 0;
}