1. 程式人生 > >單鏈表實現兩個長整數相乘

單鏈表實現兩個長整數相乘

#include<iostream.h>
#include<stdlib.h>
#include<string.h>

#define MAX 100
#define toInt(a) (*(a)-'0') 

typedef struct Node
{
	int val;
	struct Node* next;
}pNode;

enum RET_STATUS
{
	RET_ERROR,
	RET_OK
};

/**
*判斷字串合法性
*/
int isValid(char *p)
{
	if(NULL == p || '\0' == *p)
	{
		return RET_ERROR;
	}
	if( '-' == *p || '+' == *p)
	{
		p++;
	}
	while('\0' != *p)
	{
		if('0' > *p || '9' < *p)
		{
			return RET_ERROR;
		}
		p++;
	}

	return RET_OK;
}

/**
*去掉長整數正負號和多餘的0
*/
char* clearStr(char* str)
{
	if('+' == *str || '-' == *str)
		str++;
	while('0' == *str)
	{
		str++;
	}
	return str;
}

/**
*設定相乘後的正負號
*/
pNode* setSign(pNode* head, char* str1, char* str2)
{
	if((('-' == *str1)&&('-' != *str2)) || (('-' != *str1)&&('-' == *str2)))
	{
		head->val = -1;
	}
	return head;
}

/**
*將兩個長整數相乘的結構存入單鏈表
*/
pNode* multiply(pNode* head, char* pStr1, char* pStr2)
{
	int len1;
	int len2;
	int i;				
	int j;
	int carry;			//進位標誌
	pNode* ptr = head;
	pNode* pTemp;
	head = setSign(head, pStr1, pStr2);

	//先過濾掉符號和前面可能多餘的0
	pStr1 =	clearStr(pStr1); 
	pStr2 = clearStr(pStr2);
	len1 = strlen(pStr1);
	len2 = strlen(pStr2);

	//首先每位相乘,不考慮進位
	for(i = len1-1; i >= 0; i--)
	{
		ptr = head;
		//找到指標前一個位置
		for(j = 1; j < len1 - i; j++)
		{
			ptr = ptr->next; 
		}		
		for(j = len2-1; j >= 0; j--)
		{
			if(NULL == ptr->next)
			{
				pTemp = (pNode*)malloc(sizeof(pNode));
				if(NULL == pTemp)
				{
					return NULL;
				}
				pTemp->next = NULL;
				pTemp->val = 0;
				ptr->next =pTemp;
			}
			ptr = ptr->next;
			ptr->val += toInt(pStr1+i)*toInt(pStr2+j);			
		}		
	}
	//迴圈進位
	ptr = head;
	carry = 0;
	while(NULL != ptr->next)
	{
		ptr = ptr->next;
		ptr->val +=  carry;		//先考慮前一次進位
		carry = ptr->val/10;	//再設定下一次進位
		ptr->val %= 10;			//最後賦餘10之後的值
	}	
	//處理最後一次進位
	if(0 != carry)				
	{
		pTemp = (pNode*)malloc(sizeof(pNode));
		if(NULL == pTemp)
		{
			return NULL;
		}
		pTemp->next = NULL;
		pTemp->val = carry;
		ptr->next =pTemp;
	}
	return head;
}

/**
*採用遞迴方法,列印單鏈表表示的長整數
*/
void print(pNode* head)
{
	if(NULL != head->next)
	{
		print(head->next);
	}
	cout<<head->val;
}

/**
*釋放空間
*/
void release(pNode* head)
{
	pNode* ptr = head;
	pNode* ptr1;
	while(NULL != ptr)
	{
		ptr1 = ptr->next;
		free(ptr);
		ptr = ptr1;
	}
}

int main()
{
	pNode * head;
	char str1[MAX];
	char str2[MAX];
	cout<<"請輸入兩個長整數:"<<endl;
	cin>>str1>>str2;
	
	//對兩個相乘數的合法性進行判斷
	while(!isValid(str1) || !isValid(str2))
	{
		cout<<"輸入長整數不合法,請重新輸入!"<<endl;
		cin>>str1>>str2;		
	}

	//初始化單鏈表
	head = (pNode*)malloc(sizeof(pNode));
	if( NULL == head)
	{
		cout<<"Error when initing!"<<endl;
		return 0;
	}
	head->val = 1; //頭結點正負標誌,1為正,-1為負
	head->next = NULL;
	
	//採用單鏈表實現長整數相乘
	head = multiply(head, str1, str2);
	if(NULL == head)
	{
		cout<<"記憶體分配出錯!"<<endl;
		return 0;
	}
	
	//輸出單鏈表表示的長整數
	if( -1 == head->val)
	{
		cout<<"-";
	}
	if(NULL != head->next)
	{
		print(head->next);
		cout<<endl;
	}

	//釋放記憶體空間
	release(head);
	return 0;
}