单链表实现大数加法、大数减法、大数乘法、大数指数运算
2015-11-15 00:51
651 查看
Algorithm description
1、The component of the algorithm is little, simple simulation accounts for the most.
2、Addition and subtraction are base operations,
Multiplication bases on the addition and exponentiation bases on the Multiplication.
3、All the operation begins from the lowest order so in the linked list the digit with an order n points to the digit with the order n+1, for example one:
num:1234
linked list:
4、When outputting a list, the digit with a higher order should come first than that with a lower order, but in the list , access to a digit with an order n is impossible unless the digit with the order n-1 is known. To overcome this problem, there must be a function to reverse the list, continue for the example one:linked list after reversing:
5、For the exponentiation operation, there is an algorithm:
exp(a,n)= a*exp(a,n-1), when n is even(exp(a*a,n/2), when n is odd.)
Analysis and discussion
There are many bugs in fact.
When the number is negative, function will delete the sign ‘-‘, which is inevitable to change the origin number, making it to be positive. So, a number should only be used once. For example, exp(-1,3)=mul(-1,exp(-1,2)), exp(-1,2) will be called prior to mul(), -1 become 1 after exp(-1,2), so mul(-1,exp(-1,2)) become mul(1,exp(-1,2)), that is the problem.
1、The component of the algorithm is little, simple simulation accounts for the most.
2、Addition and subtraction are base operations,
Multiplication bases on the addition and exponentiation bases on the Multiplication.
3、All the operation begins from the lowest order so in the linked list the digit with an order n points to the digit with the order n+1, for example one:
num:1234
linked list:
4、When outputting a list, the digit with a higher order should come first than that with a lower order, but in the list , access to a digit with an order n is impossible unless the digit with the order n-1 is known. To overcome this problem, there must be a function to reverse the list, continue for the example one:linked list after reversing:
5、For the exponentiation operation, there is an algorithm:
exp(a,n)= a*exp(a,n-1), when n is even(exp(a*a,n/2), when n is odd.)
Analysis and discussion
There are many bugs in fact.
When the number is negative, function will delete the sign ‘-‘, which is inevitable to change the origin number, making it to be positive. So, a number should only be used once. For example, exp(-1,3)=mul(-1,exp(-1,2)), exp(-1,2) will be called prior to mul(), -1 become 1 after exp(-1,2), so mul(-1,exp(-1,2)) become mul(1,exp(-1,2)), that is the problem.
#include<iostream> #include<cstdio> #include<cmath> #include<cassert> #include<ctime> #define MAXN 10000000 using namespace std; int arr1[MAXN+5]; int arr2[MAXN+5]; struct Node{ int value; Node *adj; Node(int v,Node *n){ value=v; adj=n; } }; Node *Add(Node *,Node *); Node *Sub(Node *,Node *); Node *Reverse(Node *L){ Node *head,*tail,*p; p=new Node(L->value,NULL); L=L->adj; head=tail=p; p->adj=head; while(L){ p=new Node(L->value,NULL); L=L->adj; p->adj=head; head=p; } tail->adj=NULL; return head; } int Compare(Node *minuend, Node *subtractor){/*a>b return 1,a==b return 0,a<b return -1*/ int NumPowerMinuend=0,NumPowerSubtractor=0; Node *tmpMinuend=minuend,*tmpSubtractor=subtractor; while(tmpMinuend||tmpSubtractor){ if(NULL!=tmpMinuend){ NumPowerMinuend++; tmpMinuend=tmpMinuend->adj; } if(NULL!=tmpSubtractor){ NumPowerSubtractor++; tmpSubtractor=tmpSubtractor->adj; } } if(NumPowerMinuend>NumPowerSubtractor){ return 1; } else if(NumPowerMinuend<NumPowerSubtractor){ return -1; } else{ tmpMinuend=Reverse(minuend),tmpSubtractor=Reverse(subtractor); while(tmpMinuend&&tmpSubtractor){ if(tmpMinuend->value>tmpSubtractor->value){ return 1; } else if(tmpMinuend->value<tmpSubtractor->value){ return -1; } else{ return 0; } tmpMinuend=tmpMinuend->adj; tmpSubtractor=tmpSubtractor->adj; } } } Node *CreatList(string str){ int len=str.length(); Node *p=new Node(str[len-1]-'0',NULL);/*Create the head node firstly*/ Node *tail=p; if(len==1) return tail; p=new Node(str[len-2]-'0',NULL); Node *head=p; tail->adj=head; for(int i=len-3;i>=0;i--){ Node *p=new Node(str[i]-'0',NULL); head->adj=p; head=p; } /*while(tail){ cout<<tail->value; tail=tail->adj; }*/ return tail; } bool IsNegative(Node *L){ while(L->adj){ L=L->adj; } if(L->value==-3){ return true; } return false; } Node *Add(Node *L1,Node *L2){ int sign=1; /*Begin:Judge whether one of L1->value and L2->value is negative or not*/ bool tmp1=IsNegative(L1),tmp2=IsNegative(L2); if(false==tmp2&&true==tmp1){/*-a+b==b-a*/ Node *tmpHead=L1; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } delete(tmpHead->adj->adj);/*Delete the sign '-'*/ tmpHead->adj=NULL; return Sub(L2,L1); } else if(false==tmp1&&true==tmp2){/*a+(-b)==a-b*/ Node *tmpHead=L2; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } delete(tmpHead->adj->adj);/*Delete the sign '-'*/ tmpHead->adj=NULL; return Sub(L1,L2); } else if(tmp1&&tmp2){/*(-a)+(-b)==-(a+b)*/ sign=-1; Node *tmpHead=L2; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } delete(tmpHead->adj->adj); tmpHead->adj=NULL; tmpHead=L1; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } delete(tmpHead->adj->adj); tmpHead->adj=NULL; } /*End:Judge whether one of L1->value and L2->value is negative or not*/ /*a+b,a and b are positive*/ Node *tail,*p; int carry=0; p=new Node((*L1).value+(*L2).value,NULL); L1=L1->adj;L2=L2->adj; while((*p).value>=10){ carry++; (*p).value-=10; } tail=p; Node *head=tail; tail->adj=head; while(L1&&L2){ p=new Node((*L1).value+(*L2).value+carry,NULL); L1=L1->adj;L2=L2->adj; carry=0; while((*p).value>=10){ carry++; (*p).value-=10; } head->adj=p; head=p; } while(L1){/*The length of L1 is longer than that of L2*/ // cout<<"L1"<<(*L1).value<<"+"<<carry<<endl; p=new Node((*L1).value+carry,NULL); carry=0; while((*p).value>=10){ carry++; (*p).value-=10; } head->adj=p; head=p; L1=L1->adj; } while(L2){/*The length of L2 is longer than that of L1*/ //cout<<"L2"<<(*L2).value<<"+"<<carry<<endl; p=new Node((*L2).value+carry,NULL); carry=0; while((*p).value>=10){ carry++; (*p).value-=10; } head->adj=p; head=p; L2=L2->adj; } if(carry!=0){ int tmpCarry,power=10; while(carry>=10){/*If the carry is larger than 9*/ tmpCarry=carry; while(tmpCarry>=10){ tmpCarry-=10; } p=new Node(tmpCarry,NULL); head->adj=p; head=p; carry=(carry-tmpCarry)/power; power*=10; } p=new Node(carry,NULL); head->adj=p; head=p; } if(-1==sign){/*Both L1->value and L2->value are negative*/ p=new Node(-3,NULL); head->adj=p; head=p; } if(head==tail){ tail->adj=NULL; } return tail; } Node *Sub(Node *minuend, Node *subtractor){ int sign=1; /*BEGIN:Judge whether L1->value and L2->value is negative or not*/ bool tmp1=IsNegative(minuend),tmp2=IsNegative(subtractor); if(false==tmp2&&true==tmp1){/*-a-(+b)==-(a+b)*/ Node *tmpHead=minuend; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } tmpHead->adj=NULL;/*Delete the sign '-'*/ Node *tail=Add(subtractor,minuend); tmpHead=tail; while(tmpHead->adj){ tmpHead=tmpHead->adj; } Node *p=new Node(-3,NULL);/*Add the sign '-'*/ tmpHead->adj=p; return tail; } else if(tmp2&&tmp1){/*-a-(-b)==b-a*/ Node *tmpHead=minuend; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } tmpHead->adj=NULL;/*Delete the sign '-'*/ tmpHead=subtractor; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } tmpHead->adj=NULL;/*Delete the sign '-'*/ Node *tmp=minuend; minuend=subtractor; subtractor=tmp; } else if(false==tmp1&&true==tmp2){/*a-(-b)==a+b*/ Node *tmpHead=subtractor; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } tmpHead->adj=NULL;/*Delete the sign '-'*/ return Add(minuend,subtractor); } /*END:Judge whether L1->value and L2->value is negative or not*/ /*a-b, a and b are positive*/ int flag=Compare(minuend,subtractor); if(-1==flag){/*Make sure that minuend->value is greater than subtractor */ sign=-1; Node *tmp=minuend; minuend=subtractor; subtractor=tmp; } else if(0==flag){ return 0; } int carry=0; Node *head,*tail,*p; p=new Node(minuend->value-subtractor->value,NULL); minuend=minuend->adj;subtractor=subtractor->adj; while(p->value<0){ carry+=1; p->value+=10; } head=tail=p; head->adj=p; while(subtractor){ p=new Node(minuend->value-subtractor->value-carry,NULL); carry=0; minuend=minuend->adj;subtractor=subtractor->adj; while(p->value<0){ carry+=1; p->value+=10; } head->adj=p; head=p; } if(-1==sign){ p=new Node(-3,NULL); head->adj=p; head=p; } if(head==tail){ tail->adj=NULL; } return tail; } void Print(Node *L){ Node *head,*tail,*p; head=Reverse(L); Node *OutputNode=head; if(-3==OutputNode->value){ // cout<<-1<<endl; cout<<"-"; } else{ // cout<<-2<<endl; cout<<OutputNode->value; } OutputNode=OutputNode->adj; while(OutputNode){ cout<<OutputNode->value; OutputNode=OutputNode->adj; } } Node *ToPower(Node *L,int NumPower){ Node *p; for(int i=1;i<=NumPower;i++){ p=new Node(0,NULL); p->adj=L; L=p; } return L; } Node *Mul(Node *L1,Node *L2){ int sign=1; /*BEGIN:Judge the sign of answer and delete the sign '-' where it exists*/ bool tmp1=IsNegative(L1),tmp2=IsNegative(L2); if(false==tmp1&&true==tmp2){/* a*(-b) */ sign=-1; Node *tmpHead=L2; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } tmpHead->adj=NULL;/*Delete the sign '-'*/ } else if(true==tmp1&&false==tmp2){/* (-a)*b */ sign=-1; Node *tmpHead=L1; while(tmpHead->adj->adj){ tmpHead=tmpHead->adj; } tmpHead->adj=NULL;/*Delete the sign '-'*/ } else if(true==tmp1&&true==tmp2){ Node* tmpHead1=L2; while(tmpHead1->adj->adj){ tmpHead1=tmpHead1->adj; } tmpHead1->adj=NULL;/*Delete the sign '-'*/ Node *tmpHead=L1; while(tmpHead->adj&&tmpHead->adj->adj){ tmpHead=tmpHead->adj; } tmpHead->adj=NULL;/*Delete the sign '-'*/ } /*END;Judge the sign of answer and delete the sign '-' where it exists*/ /* a*b, a and b are positive*/ Node *tmpAnstail,*AnsTail,*p; int NumPower=0; while(L2){ // cout<<"L2->VALUE"<<L2->value<<endl; tmpAnstail=L1; for(int i=1;i<L2->value;i++){/*a*b=b+b+...+b(plus for a-1 times)*/ tmpAnstail=Add(tmpAnstail,L1); } if(0==NumPower){/* Create the head node of the answer*/ AnsTail=tmpAnstail; } else{/* Create new node of the answer*/ AnsTail=Add(AnsTail,ToPower(tmpAnstail,NumPower)); } NumPower++; L2=L2->adj; } if(-1==sign){ Node *tmpHead=AnsTail; while(tmpHead->adj){ tmpHead=tmpHead->adj; } tmpHead->adj=new Node(-3,NULL); } return AnsTail; } Node *Exp(Node *L,int NumExponent){ if(0==NumExponent){ return new Node(1,NULL); } else if(1==NumExponent){ return L; } if(NumExponent&1){ return Mul(L,Exp(L,NumExponent-1)); } return Exp(Mul(L,L),NumExponent/2); } int main(void) { freopen("output.txt","w",stdout); Node *L1=CreatList("823456780"); Node *L2=CreatList("222222222"); Node *L3=CreatList("-1111"); Node *L4=CreatList("-3333"); Node *L5=CreatList("2222"); Node *L6=CreatList("4444"); Node *L7=CreatList("2"); Node *L8=CreatList("-1"); Node *L9=CreatList("5555"); Node *L10=CreatList("-666"); Node *L11=CreatList("111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); Node *L12=CreatList("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"); Node *L13=CreatList("-333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"); /*FOR GEVERAL INTEGER */ /* Print(Add(L1,L2)); Print(Add(L4,L3));//-a+(-b) Print(Add(L4,L6));//-a+b Print(Add(L5,L3));//a+(-b) Print(Add(L5,L6));//a+b */ /* Print(Sub(L6,L5)); //a-b(a>b) Print(Sub(L5,L6)); //a-b(a<b) Print(Sub(L3,L5)); //-a-b Print(Sub(L3,L4)); //-a-(-b) */ /* Print(Mul(L7,L9));//a*b Print(Mul(L3,L7)); //a*(-b) Print(Mul(L10,L4)); //(-a)*(-b) Print(Mul(L4,L9)); //(-a)*b */ /* Print(Exp(L6,10)); Print(Exp(L4,3));//Error! */ /*FOR BIG INTEGER*/ /* Print(Exp(L12,10)); Print(Add(L13,L12)); Print(Mul(L12,L13)); Print(Sub(L13,L12)); */ return 0; }
相关文章推荐
- C#定义并实现单链表实例解析
- C语言实现单链表逆序与逆序输出实例
- C语言单链表常见操作汇总
- C数据结构之单链表详细示例分析
- C++中单链表的建立与基本操作
- 深入单链表的快速排序详解
- java实现单链表中是否有环的方法详解
- java大数乘法的简单实现 浮点数乘法运算
- Python单链表的简单实现方法
- Go语言单链表实现方法
- 结构之美:在单链表指定位置插入数据
- 《编程之美》3.4:没有头结点的单链表如何删除结点
- 结构之美:使用尾插法创建单链表
- 单链表实现
- 单链表的实现及其操作
- 判断单链表是否有环
- 单链表建环,无环链表变有环
- 用头插法实现单链表整表创建
- 单链表的删除某个元素的操作
- 单链表的插入与遍历操作