您的位置:首页 > 其它

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

2013-12-19 10:20 519 查看
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位置插入即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息