大數相乘(分治法實現時間複雜度為O(n^1.59))
阿新 • • 發佈:2019-02-12
/* * Author: dengzhaoqun * Date: 2011/04/11 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LENGTH 1000 //------------define the data struct-------------------- typedef struct { char *cptr; int len; }CharNum; //------------the end of defining data struct---------- //------the methods' declaration------ void DelHeadZero(CharNum *Result); CharNum *DoMinus(CharNum *A,CharNum *B,int *flag); int GetMax(int x,int y); int GetMin(int x,int y); CharNum *GetNum(char ch); void Init(char *ch,int len); CharNum *Merge(CharNum *AC,CharNum *BD,CharNum *ABDC,int k,int flagABDC); void MergeAdd(CharNum *des,CharNum *source,int k); void MergeMinus(CharNum *des,CharNum *source,int k); CharNum *Multiple(CharNum *X,CharNum *Y); void ShowCharNum(CharNum *Result); void ToChars(int mul,CharNum *Result); void TopDown(CharNum *chN); char *ToStr(CharNum *chN); //----end of method declaration----- //-------------the main method-------------- int main() { CharNum *X; CharNum *Y; CharNum *Result; //init X=NULL; Y=NULL; Result=NULL; //get X,Y X=GetNum('X'); Y=GetNum('Y'); Result=Multiple(X,Y); ShowCharNum(Result); free(X); free(Y); free(Result); getchar(); return 0; } //------------------the end of main method------------------ //-----------begin the method of TopDown--------------- void TopDown(CharNum *chN) { int i; int j; int k; char *ch; j=chN->len-1; while(chN->cptr[j]!='#') { j--; } ch=(char *)malloc(j*sizeof(char)); k=j-1; i=0; for(i,k;i<j;k--,i++) { ch[i]=chN->cptr[k]; } i=0; for(i;i<j;i++) { chN->cptr[i]=ch[i]; } free(ch); } //-----------end of method TopDown-------------- //-----------implement the method of getNum------------- CharNum *GetNum(char ch) { CharNum *chN; chN=(CharNum *)malloc(sizeof(CharNum)); chN->cptr=NULL; chN->len=0; chN->cptr=(char *)malloc(MAX_LENGTH*sizeof(char)); Init(chN->cptr,MAX_LENGTH); chN->len=MAX_LENGTH; printf("Input the value of %c(length<=)",ch); printf("%d",MAX_LENGTH-2); printf(" teminated by '#'):"); scanf("%s",chN->cptr); if(strlen(chN->cptr)>(MAX_LENGTH-2)) { chN->cptr[MAX_LENGTH-2]='#'; chN->cptr[MAX_LENGTH-1]='/0'; } TopDown(chN); DelHeadZero(chN); chN->len=chN->len-1; //delete the end '/0' character chN->len=chN->len-1; //delete the end '#' character return chN; } //-------------end of method getNum---------------- //-------------begin of method ToStr-------------- char *ToStr(CharNum *chN) { int i; char *str=(char *)malloc((chN->len+1)*sizeof(char)); i=0; for(i;i<chN->len;i++) { str[i]=chN->cptr[i]; } str[chN->len]='/0'; return str; } //-----------------end of method ToStr-------------- //-----------------begin of method DelHeadZero------------ void DelHeadZero(CharNum *Result) { int i; i=Result->len-1; for(i;i>=0;i--) { if(Result->cptr[i]=='0') { Result->len--; } else { break; } } } //-----------------end of method DelHeadZero-------- //-----------------begin of method ToChars---------- void ToChars(int mul,CharNum *Result) { //the max length of DoMutiple's result length is 2 Result->cptr[0]=mul%10+'0'; Result->cptr[1]=mul/10+'0'; DelHeadZero(Result); } //-----------------end of method ToChars-------------- //-------------begin of method DoMultiple--------- CharNum *DoMultiple(CharNum *X,CharNum *Y) { char *chx; char *chy; CharNum *Result; int inx; int iny; int mul; chx=NULL; chy=NULL; chx=ToStr(X); chy=ToStr(Y); inx=atoi(chx); //atoi() need the '/0' character, so ToStr() iny=atoi(chy); mul=inx*iny; Result=(CharNum *)malloc(sizeof(CharNum)); Result->len=X->len+Y->len; Result->cptr=(char *)malloc((Result->len)*sizeof(char)); ToChars(mul,Result); free(chx); free(chy); return Result; } //-----------------end of method DoMultiple---------------- //-----------------begin method GetMax---------------- int GetMax(int x,int y) { return(x>=y?x:y); } //-----------------end method GetMax------------- //-----------------begin method GetMin---------- int GetMin(int x,int y) { return(x>=y?y:x); } //-----------------end of method GetMin--------------- //-----------------begin of method Init------------ void Init(char *ch,int len) { int i=0; for(i;i<len;i++) { ch[i]='0'; } } //----------------end of method Init----------------- //------------------begin of method DoMinus---------- CharNum *DoMinus(CharNum *A,CharNum *B,int *flag) { CharNum *Result; int i; char *cha; char *chb; int flags; Result=(CharNum *)malloc(sizeof(CharNum)); Result->len=GetMax(A->len,B->len); Result->cptr=(char *)malloc((Result->len)*sizeof(char)); cha=(char *)malloc((Result->len)*sizeof(char)); chb=(char *)malloc((Result->len)*sizeof(char)); Init(Result->cptr,Result->len); Init(cha,Result->len); Init(chb,Result->len); i=0; for(i;i<A->len;i++) { cha[i]=A->cptr[i]; } i=0; for(i;i<B->len;i++) { chb[i]=B->cptr[i]; } i=0; flags=0; for(i;i<Result->len;i++) { if(cha[i]-chb[i]-flags>=0) { Result->cptr[i]=cha[i]-chb[i]-flags+'0'; flags=0; } else { Result->cptr[i]=10+cha[i]-chb[i]-flags+'0'; if(i<Result->len-1) { flags=1; } else { *flag=1; } } } // if(*flag==1)get the negative value if((*flag)==1) { Init(Result->cptr,Result->len); i=0; flags=0; for(i;i<Result->len;i++) { if(chb[i]-cha[i]-flags>=0) { Result->cptr[i]=chb[i]-cha[i]-flags+'0'; flags=0; } else { Result->cptr[i]=10+chb[i]-cha[i]-flags+'0'; flags=1; } } } free(cha); free(chb); DelHeadZero(Result); return Result; } //-----------------end of method DoMinus----------------- //---------------begin of method MergeAdd--------------- void MergeAdd(CharNum *des,CharNum *source,int k) { int flags; int i; i=k; flags=0; for(i;i<k+source->len;i++) { if((source->cptr[i-k]-'0')+(des->cptr[i]-'0')+flags>=10) { des->cptr[i]=source->cptr[i-k]+(des->cptr[i]-'0')+flags-10; flags=1; } else { des->cptr[i]=source->cptr[i-k]+(des->cptr[i]-'0')+flags; flags=0; } } des->cptr[k+source->len]=des->cptr[k+source->len]+flags; } //-----------------end of method MergeAdd----------------------------- //-----------------begin of method MergeMinus------------------------ void MergeMinus(CharNum *des,CharNum *source,int k) { int flags; int i; i=k; flags=0; for(i;i<k+source->len;i++) { if((des->cptr[i])-(source->cptr[i-k])-flags>=0) { des->cptr[i]=(des->cptr[i])-(source->cptr[i-k])-flags+'0'; flags=0; } else { des->cptr[i]=10+(des->cptr[i])-(source->cptr[i-k])-flags+'0'; flags=1; } } i=k+source->len; for(i;i<des->len;i++) { if(des->cptr[i]-'0'-flags>=0) { des->cptr[i]=des->cptr[i]-flags; flags=0; } else { des->cptr[i]=des->cptr[i]-flags+10; flags=1; } } } //----------------end of method MergeMinus------------ //-----------------begin of method Merger------------- CharNum *Merge(CharNum *AC,CharNum *BD,CharNum *ABDC,int k,int flagABDC) { CharNum *Result; int len; int i; len=AC->len+2*k+1; Result=(CharNum *)malloc(sizeof(CharNum)); Result->len=len; Result->cptr=(char *)malloc(len*sizeof(char)); Init(Result->cptr,len); i=0; MergeAdd(Result,BD,0); MergeAdd(Result,BD,k); MergeAdd(Result,AC,k); MergeAdd(Result,AC,2*k); if(0==flagABDC) { MergeAdd(Result,ABDC,k); } if(1==flagABDC) { MergeMinus(Result,ABDC,k); } DelHeadZero(Result); return Result; } //------------------end of method Merge-------------- //-------------begin of method Multiple-------------- CharNum *Multiple(CharNum *X,CharNum *Y) { CharNum *Result; CharNum *A,*B,*C,*D; CharNum *AC,*BD,*A_B,*D_C,*ABDC; int k; int flag[3]={0};//flag[0] represent the sign of (A-B) , //flag[1]--(D-C),flag[2]--(A-B)(D-C) //init Result=NULL; A=(CharNum *)malloc(sizeof(CharNum)); A->cptr=NULL; A->len=0; B=(CharNum *)malloc(sizeof(CharNum)); B->cptr=NULL; B->len=0; C=(CharNum *)malloc(sizeof(CharNum)); C->cptr=NULL; C->len=0; D=(CharNum *)malloc(sizeof(CharNum)); D->cptr=NULL; D->len=0; AC=NULL; BD=NULL; A_B=NULL; D_C=NULL; ABDC=NULL; if((X->len==0)||(Y->len==0)) { Result=(CharNum *)malloc(sizeof(CharNum)); Result->cptr=NULL; Result->len=0; return Result; } else if((X->len==1)&&(Y->len==1)) { Result=DoMultiple(X,Y); } else { k=(GetMax(X->len,Y->len)-1)/2+1; if(k<GetMin(X->len,Y->len)) { A->cptr=&(X->cptr[k]); A->len=X->len-k; B->cptr=X->cptr; B->len=k; DelHeadZero(B); C->cptr=&(Y->cptr[k]); C->len=Y->len-k; D->cptr=Y->cptr; D->len=k; DelHeadZero(D); } else if(k>=X->len) { B->cptr=X->cptr; B->len=X->len; DelHeadZero(B); C->cptr=&(Y->cptr[k]); C->len=Y->len-k; D->cptr=Y->cptr; D->len=k; DelHeadZero(D); } else if(k>=Y->len) { A->cptr=&(X->cptr[k]); A->len=X->len-k; B->cptr=X->cptr; B->len=k; DelHeadZero(B); D->cptr=Y->cptr; D->len=k; DelHeadZero(D); } AC=Multiple(A,C); BD=Multiple(B,D); A_B=DoMinus(A,B,&flag[0]); D_C=DoMinus(D,C,&flag[1]); ABDC=Multiple(A_B,D_C); if(flag[0]!=flag[1]) { flag[2]=1; } Result=Merge(AC,BD,ABDC,k,flag[2]); } //free the memory free(A); free(B); free(C); free(D); free(AC); free(BD); free(A_B); free(D_C); free(ABDC); return Result; } //--------------------end of method Multiple----------------------- //--------------------begin of method ShowCharNum------------- void ShowCharNum(CharNum *Result) { int i; printf("The multiple result is: "); i=Result->len-1; for(i;i>=0;i--) { printf("%c",Result->cptr[i]); } printf("/n"); } //--------------------end of method ShowCharNum-----------------