1. 程式人生 > >大數相乘(分治法實現時間複雜度為O(n^1.59))

大數相乘(分治法實現時間複雜度為O(n^1.59))

/*
 * 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-----------------