题目如上
这题考了一个数据结构,就是链表。
这里假如你是个初学者,没有简单了解数据结构是什么,我在这里简单讲解一下。
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。简单来说就是两块非连续的地址,然后在每个地址末尾加一个指针指向下一块地址,这种地址指向接着地址就是链表结构
这里拿题目给的2 -> 4 -> 3举例子
我声明的变量要怎么做到保留自己该有的属性的同时,还要有一个指针能指向我下一个数据的地址呢?
这就要用到C语言的一个关键字 struct 了 。
struct(结构体)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构体。
结构体定义由关键字 struct 和结构体名组成,结构体名可以根据需要自行定义。
语法是这样的:
struct tag
{
member-list;
member-list;
member-list;
...
} variable-list;
就好比我要做个游戏,我有个角色叫Richard。
我要用结构体写的话就是
struct Richard
{
int hp;
int mp;
int atk;
};
假如我要把他的hp改为100,访问它的数据我就可以这样访问 Richard.hp = 100 。
链表结构如果用struct表达的话,可以是这样
这样我们回到那个2 -> 4 -> 3的例子里
其实就是
注意:
链表末尾的指向要设定,如果没有指定的东西就要把它指向为空,就是*next = NULL
指针如果没有要指向的地方都推荐指向NULL。
题目解析
我们来看看题目给的初始代码
上面翻译为
/**
* 单链表节点结构体定义。
* struct ListNode {
* int val; // 节点值
* struct ListNode *next; // 指向下一节点指针
* };
*/
前面我们已经了解了这个struct的用法,那么这里在下面那串函数声明中,题目传入的两个值L1和L2的结构应该是这样。
我们接下来看这个题目解答过程
因为题目要求的是两数之和,并以相同形式返回一个表示和的链表。
所以我们在开始就要声明一个与L1和L2相同结构的变量dummy,并且分配一个匹配这种自定义变量的指针current,然后把dummy的地址给它,并且把dummy的指向改为空,这样的话就是
carry在这里是表示进一位,在前面的2 -> 4 -> 3和5 -> 6 -> 4的例子中4+6是等于10,结果我要返回的数据是0而非10,就说明要进一位,这个carry就是存储进一位的值的。
用while开始循环,退出条件为L1、L2的结果为NULL,carry的结果为0。
然后再进行声明,声明两个我要相加的值,然后通过一个三元运算符进行赋值。
如果L1此时的值为True,那么就会把L1此时所指向的链表值给val1,如果为False,则把0给val1,val2同理。
然后再声明一个sum,用来存储两个数值相加的和,并且可以加进一位。
再把carry进行计算,每次循环如果sum的值大于0,会把sum进行整除获取进一数,在sum的后面保证进一会用到下次循环上。
然后开始进行链表的后移操作,这里有个知识点。
如果我是结构体本身,那么我访问我的成员我是这样 dummy.val
如果我是一个指向结构体的指针,那么我访问结构体的成员是这样 current->val
这里第一步是要通过malloc函数开辟一块结构体空间给此时的结构体dummy中的下一指向指针。
然后把开辟的结构体空间中的值赋值为两数相和的取余,因为要保证不能大于等于10。
然后把开辟的结构体空间中的下一指向改为NULL。
可以理解为这样
然后进行判断,如果说此时L1和L2指向地址的值不是NULL,那么就会把两个指针后移一位。
就像这样
然后是current也要往后移一位
然后就是第二遍循环
第二遍相加等于10,此时carry会被赋值1,用作于下次循环的sum中
然后是第三遍,此时sum的值会加上carry的进1,所以总值为3+4+1=8。
此时循环的最后一段代码和第一段代码的组合拳会发力
因为链表只有三个,所以在三次后移以后数组没有开辟新的位置续命,指针会跟着第三块结构体的最后指向指向NULL,那么在此时达成了循环的退出条件,即L1 == NULL、L2 == NULL、carry == 0
此时循环会退出,我们只需要把三个相加的值通过链表返回就行了
我们来看下结果
顺带一提,如果while循环退出条件不要carry,此时第三种情况会出错
实际情况记得把free带上,链表是一回事敲代码好习惯又是另一回事。
本人穷鬼,无事投喂