Chapter 2 | Linked Lists--实现两个单链表数据的和

2.4     You have two numbers represented by a linked list, where each node contains a single digit.  The digits are stored in reverse order,such that the 1’s digit is at the head of the list. Write a function that adds the two numbers and returns the sum as a linked list.

EXAMPLE:

input:(3 -> 1 -> 5), (5 -> 9 -> 2)

output:(8 -> 0 -> 8)

译文: 你有两个由单链表组成的数,单链表中每个节点包含一个数字,数字是逆序存储的,也就是说个位数放在链表头结点处。写一个函数使这两个数相加并返回结果,结果也由链表表示。

例如:

输入:(3 -> 1 -> 5), (5 -> 9 -> 2)

输出:(8 -> 0 -> 8)

这道题目涉及到链表的基本操作以及异常场景用例分析。这里的异常场景主要包括:1.链表为空;2.最高位有进位;3.两个链表长度不一。

我们注意到单链表中数字是逆序存储的,所以我们在进行相加运算时,只能将低位结果对应一次地添加到新链表尾。对于场景2,我们需要在最后判断是否最高位有进位,如果有,则需要添加进位,反之,就不需要。场景3,需要判断哪个链表长,然后将长链表多余的那部分添加在新链表后面,当然在多余部分的最低位也需要考虑进位。

为此,我们首先要初始化一个单链表,将待相加数据写进去,然后编写一个链表添加函数。由于思路比较简单,直接贴代码(本系列基本上是C++编写)。

typedef struct NODE
{
	int data;
	struct NODE *pnext;
}Node;

void create(Node **pHead, int x)
{
	Node *q;

	q = new Node;
	assert(NULL != q);

	q->data = x;
	q->pnext = NULL;

	*pHead = q;

	return;
}

/*添加元素到链表尾*/
void addList(Node **pHead, int x)
{
	if (NULL == *pHead)
	{
		create(pHead, x);
		return;
	}

	Node *p, *q;
	p = *pHead;
	
	while (p->pnext)   p = p->pnext;

	q = new Node;
	assert(NULL != q);
	q->data = x;
	q->pnext = NULL;

	p->pnext = q;
	return;
}
上面针对本题可能显得比较冗杂,考虑到创建链表,添加链表属于常用,所以就都用上了。下面部分代码的功能是将数组写入链表中,链表中的数据的先后顺序和数组中的先后顺序保持一致,单独将各个功能函数分离处理,有利于程序的“高内聚,低耦合”。

void readToNode(Node **pHead, int a[], int size)
{
	if ((NULL == *pHead) || (NULL == a))
		return;

	Node *p = *pHead;
	p->data = a[0];

	for (int i = 1; i < size; ++i)
	{
		addList(&p, a[i]);
	}
	return;
}

最后是运算部分代码

Node* bignumberplus(Node *p, Node *q)
{
	if (NULL == p)  return q;
	if (NULL == q)  return p;

	Node *result = NULL;

	int data, carry;
	carry = 0;

	for (; ((p != NULL) && (q != NULL)); p = p->pnext, q = q->pnext)
	{
		data = (p->data + q->data + carry) % 10;
		addList(&result, data);
		carry = (p->data + q->data + carry) / 10;
	}

	if (p != NULL)
	{
		/*data = (p->data + carry) % 10;
		addList(&result, data);
		carry = (p->data + carry) / 10;
		p = p->pnext;*/      //998+2=1000 这种情况下测试出错
		while (p)  //只有p则直接添加到result后
		{
			data = (p->data + carry) % 10;
		        addList(&result, data);
		        carry = (p->data + carry) / 10;
		        p = p->pnext;
		}
		if (carry)   //最高位进位的情况
			addList(&result, carry);
		return result;
	}
	else if (q != NULL)
	{
		/*data = (q->data + carry) % 10;
		addList(&result, data);
		carry = (q->data + carry) / 10;
		q = q->pnext;*/
		while (q)
		{
		        data = (q->data + carry) % 10;
		        addList(&result, data);
		        carry = (q->data + carry) / 10;
		        q = q->pnext;*/
		}
		if (carry)
			addList(&result, carry);
		return result;
	}
	if (carry)
		addList(&result, carry);
	return result;
}
主要是长度不一和进位的处理上注意一下,程序看上去不够优化,直接贴出来了。测试代码

int main()
{
	Node *p, *q, *result;
	create(&p, 0);
	create(&q, 0);

	int a[] = { 9, 9, 9 };
	int b[] = { 1, 1, 1, 9 };
	int size_a = sizeof(a) / sizeof(a[0]);
	int size_b = sizeof(b) / sizeof(b[0]);
	readToNode(&p, a, size_a);
	readToNode(&q, b, size_b);

	result = bignumberplus(p, q);
	print(result);

	return 0;
}

结果为0,1,1,0,1,反过来就是999+9111=10110。

如果按照标准排序,即数字顺序存储,最低位在链表尾,那么我们就采用指定位置插入链表函数,每次在0位置插入即可。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值