#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int val;
struct ListNode *next; //ListNode类型指针;
};
链表的创建:创建一个结构体类型,元素包括【数据域】与【指针域】,每个链上的节点地址要赋值给上一节点的【指针域】(头节点除外)。
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode dummy = {0, NULL};
struct ListNode *p = &dummy;
int carry = 0;
创建虚拟的头节点dummy,数据为0,地址为空(当要创建新节点再赋值);
不像数组那样有序,链表节点的地址是分散的,因而要创建指针p,当要处理新的节点时,通过指针找到节点。
carry是进位值,比如个位的6+6得2进1,1即进位值。由于每个节点充当一位,因此进位值要单独存放并交到下个对节点的相加。
while (l1 || l2 || carry) {
int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + carry;
//节点数据和进位值相加
carry = sum / 10;
p->next = (struct ListNode *)malloc(sizeof(struct ListNode));
p = p->next; //给下一个节点地址赋值到指针,p不再指向dummy
p->val = sum % 10;
p->next = NULL;
l1 = l1 ? l1->next : l1; //如果l1、2不为空,链的下一个变量继续
l2 = l2 ? l2->next : l2;
}
while里面三个 || ,只要有一个不为0,条件成立;当l1、l2、carry都为0,意味着加完了;
sum时要询问l1、2是否为空;
sum、carry结束后,要创建新节点(假设节点1),把sum%10(即去掉进位值留下的个位数):
- 通过malloc函数在动态内存空间为节点1开辟空间,此函数返回新内存空间的首地址,类型强转换(struct ListNode *)后变为指针变量,并赋值给同类型的p->next,即头节点的指针域。头节点与节点1相互链接;
- 将节点1的指针变量p ->next赋值给p,方便在while循环中层层迭代而不用多个“->”调用,p不再指向dummy;
- 节点1的next赋值为NULL,直到节点2的创建并赋值。
return dummy.next;
}
函数类型是struct ListNode*,要返回节点1的指针(第一个有效节点的指针),系统会根据节点的链接遍历整个链表;
int main() {
// 创建两个链表
struct ListNode *l1 = (struct ListNode *)malloc(sizeof(struct ListNode));
l1->val = 2;
l1->next = (struct ListNode *)malloc(sizeof(struct ListNode));
l1->next->val = 4;
l1->next->next = (struct ListNode *)malloc(sizeof(struct ListNode));
l1->next->next->val = 3;
l1->next->next->next = NULL;
struct ListNode *l2 = (struct ListNode *)malloc(sizeof(struct ListNode));
l2->val = 5;
l2->next = (struct ListNode *)malloc(sizeof(struct ListNode));
l2->next->val = 6;
l2->next->next = (struct ListNode *)malloc(sizeof(struct ListNode));
l2->next->next->val = 4;
l2->next->next->next = NULL;
// 调用相加函数
struct ListNode *result = addTwoNumbers(l1, l2);
// 打印结果
struct ListNode *p = result;
while (p) {
printf("%d ", p->val);
p = p->next;
}
return 0;
}