程序员面试金典: 9.2链表 2.5对两个用链表表示的整数求和

#include <iostream>
#include <stdio.h>

using namespace std;

const int MAXSIZE = 1000;

/*
问题:给定两个用链表表示的整数,每个节点包含一个数位。这些数位是反向存放的,也就是
      个位排在链表首部。编写函数对这两个整数求和,并用链表形式返回结果。
分析:比如两个数分别是123,789,由于个位在首部,得到如下的两个数
      3 2 1
	  9 8 7
	  2 1 9
	  最终结果为912,算的时候直接从左向右(从低位到高位算即可,读取的时候反向读取链表即可)

输入:
123 789
123 89
输出:
912
212

关键:
1 需要明白相加的两个整数长度可能不同,需要注意遍历
*/

typedef struct Node
{
	int value;
	Node* pNext;
}Node;


//构建连边,按照尾插法来做,返回节点值到出现次数的映射
void buildList(int* pArray , Node* head , int num)
{
	if(pArray == NULL)
	{
		return;
	}
	if(head == NULL)
	{
		return;
	}


	//尾插法: 保留最后一个结尾节点,将新生成的节点插入在结尾节点,并令结尾节点为当前节点
	Node* pLast = head;
	//int num = sizeof(pArray) / sizeof(int);
	for(int i = 0 ; i < num ; i++)
	{
		int value = *(pArray + i);
		Node* pNode = new Node();
		pNode->value = value;
		pLast->pNext = pNode;
		pLast = pNode;
	}
}

//这里必须先打印链表末尾,再打印末尾前面,
void printList(Node* pHead)
{
	if(NULL == pHead)
	{
		return;
	}
	printList(pHead->pNext);
	cout << pHead->value;
}

void releaseList(Node* pHead)
{
	if(NULL == pHead)
	{
		return;
	}
	Node* pNode = pHead->pNext;
	Node* pPrevious = pHead;
	while(pNode)
	{
		Node* pDeleteNode = pNode;
		pPrevious->pNext = pNode->pNext;
		pNode = pNode->pNext;
		pPrevious = pPrevious->pNext;
		delete pDeleteNode;
	}
	//删除头结点
	delete pHead;
}

//将123除10取余,123 / 10 =12余3 , 12 / 10 = 1余2 , 1 / 10 = 0余1 ,依次得到个位,10位,百位
//获取总共的位数
int getDigitNum(int num)
{
	int temp = num;
	int count = 0;
	do{
		temp /= 10;
		count++;
	}while(temp != 0);
	return count;
}

void getDigitArr(int num,int* pArr)
{
	int temp = num;
	int count = 0;
	//这里先拿到个位的,个位需要放在链表前面
	do{
		int num = temp % 10;
		pArr[count] = num;
		temp /= 10;
		count++;
	}while(temp != 0);
}

//将两个链表求和,个位是在链表首位,所加结果放在第一个链表中并返回,需要放在较长的链表中(默认是第一个)
Node* sum(Node* nNode,Node* mNode)
{
	if(nNode == NULL || mNode == NULL)
	{
		return NULL;
	}

	Node* pNNode = nNode->pNext;
	Node* pMNode = mNode->pNext;
	int pass = 0; //设置进位

	//注意,这里只能有一个不为空即可,如果另一个数为空,则按0计算
	while(pNNode || pMNode)
	{
		//所加结果需要进位
		if(pMNode == NULL)
		{
			pNNode->value += 0 + pass;
		}
		else
		{
			pNNode->value += pMNode->value + pass;
		}
		if( pNNode->value > 10)
		{
			pNNode->value -= 10;
			pass = 1;
		}
		else
		{
			pass = 0;
		}
		pNNode = pNNode->pNext;
		if(pMNode != NULL)
		{
			pMNode = pMNode->pNext;
		}
	}
	return nNode;
}




int main(int argc, char* argv[])
{
	int n,m;
	while(cin >> n >> m)
	{
		int nDigitNum = getDigitNum(n);
		int mDigitNum = getDigitNum(m);
		int* nArr = new int[nDigitNum];
		int* mArr = new int[mDigitNum];
		getDigitArr(n, nArr);
		getDigitArr(m, mArr);
		//得到两个数组之后,下面需要存入到链表中
		Node* nNode = new Node();
		buildList(nArr , nNode , nDigitNum);
		Node* mNode = new Node();
		buildList(mArr , mNode , mDigitNum);
		Node* pResult;
		if(nDigitNum >= mDigitNum)
		{
			pResult = sum(nNode,  mNode);
		}
		else
		{
			pResult = sum(mNode,  nNode);
		}

		//注意这里空节点需要排除
		printList(pResult->pNext);
		cout << endl;
		releaseList(nNode);
		//releaseList(nNode);
		releaseList(mNode);
		delete[] nArr;
		delete[] mArr;
	}
	system("pause");
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值