两个任意长度的长整数相乘(C语言、双向链表方法)

注意:本文并非华为oj原题


/*****************************************************************************

 Prototype    : multiply
 Description  : 两个任意长度的长整数相乘, 输出结果
 Input Param  : 
char * strMultiplierA  乘数A
char *  strMultiplierB  乘数B
 Output       : 
                char * strRst            乘法结果
 Return Value : 
                int                       0  正确  
                                         -1  异常
*****************************************************************************/
/*
请编写”长整数相乘”程序,实现两个任意长度的长整数(正数)相乘,输出结果.  
提示: 将长整数用一个字节链表表示,逐字节相乘,要考虑进位
 
乘数A = ∑Am*10m     ( 0 ≤ m <∞, 0 ≤ Am ≤ 9 ), 首位可以为0 
乘数B = ∑Bn*10n       ( 0 ≤ n <∞,  0 ≤ Bn≤ 9 ), 首位可以为0 
Result = 乘数A *乘数B 
 
Example1: 
乘数A = 1*101 + 2*100 = 12   ( m = 1, A1= 1, A0= 2) 
乘数B = 3*101 + 4*100 = 34   ( n = 1,  B1= 3, B0= 4) 
Example2: 
乘数A = 0*102 + 0*101 + 0*100 = 000   ( m = 2, A2= 0, A1= 0, A0= 0) 
乘数B = 0*103 + 5*102 + 6*101 + 0*100 = 0560   ( n = 3, B3= 0, B2= 5, B1= 6, B0= 0) 

*/


#include <stdio.h>
#include <malloc.h>

typedef struct NODE
{
	struct NODE * pUp;
	int shuzhi;
	struct NODE * pNext;
}*pNode;
int multiply (char * strMultiplierA, char *  strMultiplierB, char * strRst) ;
pNode InitList(char * strMultiplier);
void multiplyA(pNode pHead1, pNode pFlag, int shuzhi );
void DsXj(pNode pHeadTemp, pNode pHeadstrRst);
pNode creatList(pNode pHead);
void ShowList(pNode pHead) ;

int main(void)
{
	char strMultiplierA[100] = "987654321987654321987654321";
	char strMultiplierB[100] = "987654321987654321987654321";
	char strRst[20] = "\0";
	multiply (strMultiplierA,strMultiplierB,strRst);
	puts(strRst);
	return 0;
}

int multiply (char * strMultiplierA, char *  strMultiplierB, char * strRst) 
{

    /* 在这里实现功能 */
	pNode pHead1,pHead2,pHeadTemp,pHeadstrRst;
	pNode p1,p2,TempNode,pFlag;
	int carry;
	char * pCh;

	if(strMultiplierA == NULL || strMultiplierB == NULL || strRst == NULL)
		return -1;

	pHead1 = InitList(strMultiplierA);

	pHead2 = InitList(strMultiplierB);

	//创建链表pHeadTemp,保存单次pHead1与p2->shuzhi的乘积,pHeadTemp要比pHead1多一个节点
	pHeadTemp = creatList(pHead1);

	//创建链表pHeadstrRst,保存最终结果,pHeadstrRst要比pHeadTemp多一个节点
	pHeadstrRst = creatList(pHeadTemp);

	p2 = pHead2->pNext;
	pFlag = pHeadTemp->pNext;
	while(p2 != NULL)
	{
		//pHead1链表与p2->shuzhi的乘积
		multiplyA(pHead1, pFlag, p2->shuzhi );

		//大数求和:pHeadTemp与pHeadstrRst求和
		DsXj(pHeadTemp, pHeadstrRst);

		//p2 = p2->pNext;则多一个10n,要补零
		//须注意pHeadTemp每次都要插入一个节点,插入在第一个点,补0,因为10n
		TempNode = (pNode)malloc(sizeof(NODE));
		TempNode->shuzhi = 0;
		TempNode->pNext = pHeadTemp->pNext;
		TempNode->pUp = pHeadTemp;
		pHeadTemp->pNext = TempNode;	

		//相应的pHeadstrRst也要增加一个节点,接在最后面,用于大数相加
		p1 = pHeadstrRst;
		while(p1->pNext!=NULL)
		{
			p1 = p1->pNext;
		}
		TempNode = (pNode)malloc(sizeof(NODE));
		TempNode->shuzhi = 0;
		TempNode->pNext = NULL;
		TempNode->pUp = p1;
		p1->pNext = TempNode;

		p2 = p2->pNext;	
	}

	//使p1指向最后一个节点
	p1 = pHeadstrRst;
	while(p1->pNext!=NULL)
	{
		p1 = p1->pNext;
	}

	//使p1指向最后一个非0节点
	while((p1->shuzhi == 0) && (p1 != pHeadstrRst->pNext))
	{
		p1 = p1->pUp;
	}

	//赋值给strRst
	pCh = strRst;
	while(p1 != pHeadstrRst)
	{
		*pCh = p1->shuzhi + '0';
		pCh++;
		p1 = p1->pUp;
	}
	*pCh = '\0';

	pCh = strRst;

    return 0;
}

pNode InitList(char * strMultiplier) 
{
    /* 在这里实现功能 */
	char * pCh;
	pNode p,TempNode;
	pNode pHead;

	if(strMultiplier == NULL)
		return NULL;
	
	pCh = strMultiplier;
	while(*pCh!='\0')
	{
		pCh++;
	}
	pCh--;

	//头指针不使用,只用来作为链表头
	pHead = (pNode)malloc(sizeof(NODE));
	pHead->shuzhi = 0;
	pHead->pNext = NULL;
	pHead->pUp = NULL;
	p = pHead;

	while(pCh>=strMultiplier)
	{
		TempNode = (pNode)malloc(sizeof(NODE));
		TempNode->shuzhi = *pCh - '0';
		TempNode->pNext = NULL;
		TempNode->pUp = p;
		p->pNext = TempNode;
		p = p->pNext;

		pCh--;
	}	

    return pHead;
}

//pHead1链表与shuzhi的乘积
void multiplyA(pNode pHead, pNode pFlag, int shuzhi )
{
	pNode p, pTemp;
	int carry,temp;

	p = pHead->pNext;
	pTemp = pFlag;

	carry = 0;
	//pHead1链表乘以p2,并保存在pFlag
	while(p != NULL)
	{
		temp = (p->shuzhi) * shuzhi + carry;

		pTemp->shuzhi = temp % 10;
		
		carry = temp / 10;

		pTemp = pTemp->pNext;
		p = p->pNext;
	}
	pTemp->shuzhi = carry;

}

//大数求和:pHeadTemp与pHeadstrRst求和
void DsXj(pNode pHeadTemp, pNode pHeadstrRst)
{
	int carry,temp;
	pNode p1, p2, TempNode;

	p1 = pHeadTemp->pNext;
	p2 = pHeadstrRst->pNext;//保存结果
	carry = 0;

	while(p1!=NULL)
	{
		temp = p2->shuzhi + p1->shuzhi + carry;
		p2->shuzhi = temp%10;
		carry =  temp/10;

		p2 = p2->pNext;
		p1 = p1->pNext;
	}

		//printf("求和之后\n");
		//printf("pHeadstrRst是\n");
		//ShowList(pHeadstrRst);
		//printf("carry = %d\n",carry);

	while(carry != 0)
	{
		p2->shuzhi = (p2->shuzhi + carry)%10;
		carry =  (p2->shuzhi + carry)/10;

		//若carry!=0,且到了最后一个节点了,就增加一个新节点
		if(carry != 0 && p2->pNext == NULL)
		{
			TempNode = (pNode)malloc(sizeof(NODE));
			TempNode->shuzhi = 0;
			TempNode->pNext = NULL;
			TempNode->pUp = p2;
			p2->pNext = TempNode;
		}
		
		p2 = p2->pNext;	
	}

}

//根据pHead创建链表
pNode creatList(pNode pHead)
{
	pNode pTemp,p,TempNode,pHeadTemp;

	pHeadTemp = (pNode)malloc(sizeof(NODE));
	pHeadTemp->shuzhi = 0;
	pHeadTemp->pNext = NULL;
	pHeadTemp->pUp = NULL;
	pTemp = pHeadTemp;

	p = pHead;//使pHeadTemp、pHeadstrRst比pHead1多一个节点
	while(p != NULL)
	{
		//pHeadTemp
		TempNode = (pNode)malloc(sizeof(NODE));
		TempNode->shuzhi = 0;
		TempNode->pNext = NULL;
		TempNode->pUp = pTemp;
		pTemp->pNext = TempNode;	
		pTemp = pTemp->pNext;

		p = p->pNext;
	}

	return pHeadTemp;
}

void ShowList(pNode pHead) 
{
    /* 在这里实现功能 */
	pNode p;

	p = pHead->pNext;
	while(p!=NULL)
	{
		printf("%d",p->shuzhi);	
		p = p->pNext;
	}	
	printf("\n");
}



展开阅读全文

没有更多推荐了,返回首页