可能你不太理解什么是链表,所以无法理解这里的head、head.next、head.val。
先来画一个草图让你理解什么是链表:
['hi']--> ['Python']--> [0.618]--> [False]-->None
这就是一个链表的示意图,先来理解它的结构特点。
一个链条是由相互连接的小环组成,以上链表都是由[ ]-->结构组成的,这就是
节点你也可以理解成链条上的一环。
真实链条中的一环(除了开头和结尾)既连接着前一环也连接着下一环,而我们的节点因为只有一个-->所以它只能看到下一环是什么,也就是说示意图展示的是一个
单向链表。
我们当然可以再增加一个<--,让每个节点变为<--[ ]-->,由这样的节点构成的链表就是双向链表。不过题目中给的是单向链表,所以我们就不再讨论双向链表了。
说回节点,对于任意一个节点来说它都要保存至少
两项数据:值和下一个节点。示意图中值保存在[ ]中,-->指向下一个节点。
所以上述链表保存了思想数据,它们分别是'hi'、'Python'、0.618和False。再来看[False]-->None这个节点,为什么我们说它是最后一个节点呢?
真实情况下,这些节点保存在内存中不同位置,我们的眼睛看不到。以上链表只是“示意图”,省去了干扰我们的其他因素。之所以我们说[False]-->None是最后一个节点,因为它指向None而不是其他节点。
现在我猜你应该已经理解了链表与节点的关系(链表其实是由一个一个节点组成的,每个节点要么指向下一节点要么指向None)以及如何判断最后一个节点。
但这还不够,因为上面的那个节点其实我们根本无法访问其中的数据,'hi'、'Python'、0.618这些数据其实我们都访问不到。因为我们没有
头节点。
由于这是一个单向链表,只有理解了开头在哪里我们才能逐个访问节点直到末尾。虽然在视觉上我们可以把['hi']-->当作头节点,但在程序中我们需要手动把头节点赋值给一个变量,如此一来我们才能借助这个变量访问各个节点保存的数据。
你需要理解这些内容:节点、节点保存两项数据(值和下一节点)、头节点。
说了这么多,再来看看代码怎么写。请再看一遍题目,第2行到第5行被注释掉的部分就是一个表示链表节点的类:
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
前面我们已经知道了每个节点至少要保存两项数据,这个类的构造函数__init__中确实设置了两个属性val和next。
val保存的就是值,next保存下一个节点。默认情况下节点不指向任何节点,所以self.next = None
接下来我们使用上述节点类来创建一个链表:
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
head = ListNode('hi') # 头节点很重要,没有它以后就无法访问其他节点了
# 接下来为head增加一个新节点,方法有二,其实是一样的
# 方法一:
nd = ListNode('Python')
head.next = nd # 手动让头节点的next指向下一个节点
# 方法二:
# head.next = ListNode('Python')
# 增加第三个节点
nd.next = ListNode(0.618)
# 增加最后一个节点
nd.next.next = ListNode(False)
print(f'头节点的值{head.val}')
print(f'下一节点的值{head.next.val}')
# 如果节点的next属性指向None则说明这个节点就是末尾了
# 所以如下代码可以遍历整个链表
current = head # 一定要赋值,不能直接对head操作,否则以后无法访问到链表中的数据了
n = 1 # 只是为了计数,演示用
while current is not None:
print(f'第{n}个节点的值是{current.val}')
n += 1
current = current.next # 这一行很重要,让current指向下一节点,没有这一行程序会陷入死循环
# 到达最后一个节点时current.next的值就是None
# 所以经过current = current.next这一样代码后current is not None这个条件不成立,循环自动退出。
以上就是关于链表的head、head.next、head.val的解释,如果还有问题请继续提问。