【演算法拾遺】大數相加(不開闢額外空間)

蘭亭風雨發表於2014-05-12

轉載請註明出處:http://blog.csdn.net/ns_code/article/details/25555743


    大數相加可以藉助多種方法來實現,這裡提供了一種連結串列節點的資料域為int型(用char型也可以,這樣更省空間)的思路。這篇文章採用常用的轉變為字串進行處理的方法,下面說下我用字串實現大數相加的思路:

    假設輸入瞭如下兩個字串(其中上面的紅色部分表示陣列的下標,下面的綠色和黃色部分表示各字元):

    s1:


    s2:

    很明顯,s1的實際長度為4,s2的實際長度為7,將二者在最低位出對齊,並將前面空出來的高位用0替換,最高位留出來,以備相加到最左邊有進位時,可以儲存進位1。移位後如下所示:

    s1:


    s2:


    這裡沒有了'\0',是因為移動的時候覆蓋掉了,暫且不管,接下來我們就要執行相加的操作,由於每個字元的ASCII值均在0-255之間,因此我們沒必要在另外開闢int陣列,可以直接在char陣列上進行移位、相加等操作,只要注意不要將還沒移動或者相加的資料覆蓋掉就行。

    我們假設二者相加後的結果存放到s1中,則相加後,s1如下:


    這是次高位沒有進位,因此最高位還是0,最後我們將s1中的各int值再轉化為字元,如果s1[0]為1,則直接轉化,如果s1[0]為0,則轉化後,需要將字元依次向前移動一位,最後,在最後一個字元的後面加上'\0',表示字串的結束。這邊得到了結果。


    完整實現程式碼如下:

/******************
字串實現大數相加
Author:蘭亭風雨
Date:2014-05-11
******************/
#include<stdio.h>
#include<string.h>

#define MAX 100

char *BigDataAdd(char *s1,char *s2)
{
	if(s1==NULL || s2==NULL)
		return NULL;

	int len1 = strlen(s1);
	int len2 = strlen(s2);
	int Maxlen = (len1>len2)?len1:len2;
	
	//將對應的字元轉化為整數,並使二者對齊到Maxlen處,
	//前面的字元通過memset用ASCII值為0的字元替換,
	//最高位留出來,如果次高位發生進位,則可以儲存進位1,
	//這裡s1和s2相當於變為了整數陣列,由於字元的ASCII值在0-255之間,
	//因此這裡不用開闢int陣列,直接用自身的char陣列即可
	int i,k;
	for(i=len1-1,k=Maxlen;i>=0;i--,k--)
		s1[k] = s1[i] - '0';
	if(k>=0)
		memset(s1,0,(k+1)*sizeof(char));
	for(i=len2-1,k=Maxlen;i>=0;i--,k--)
		s2[k] = s2[i] - '0';
	if(k>=0)
		memset(s2,0,(k+1)*sizeof(char));

	//整數陣列相加到s1中
	for(i=Maxlen;i>=1;i--)
	{
		s1[i] += s2[i];
		if(s1[i]>=10)
		{
			s1[i] -= 10;
			s1[i-1] += 1;
		}
	}
	
	//將s1轉換為為相加後的字串
	if(s1[0] == 0)
	{	//如果次高位沒有進位
		for(i=1;i<=Maxlen;i++)
			s1[i-1] = s1[i] +'0';
		s1[i-1] = '\0';
	}
	else
	{	//如果次高位有進位
		for(i=0;i<=Maxlen;i++)
			s1[i] = s1[i] +'0';
		s1[i] = '\0';
	}
	return s1;
}

int main()
{
	char s1[MAX];
	char s2[MAX];
	gets(s1);
	gets(s2);
	char *result = BigDataAdd(s1,s2);
	if(result != NULL)
		puts(result);
	else
		printf("Wrong\n");
	return 0;
}

    測試結果:


    


相關文章