我已经开始研究链表了,但我不知道下一步该做什么。我知道它指向下一个对象,但它是怎么做到的?例如,下面是将新节点插入链表的代码。
class Node:
def __init__(self,data):
self.data=data
self.next=None
class ll:
def __init__(self):
ll.head=None
def insertEnd(value):
newnode = Node(value)
currentNode = l.head
while(currentNode.next):
currentNode = currentNode.next
currentNode.next = newnode
if __name__ == '__main__':
l = ll()
l.head = Node(6)
second = Node(2)
l.head.next = second
insertEnd(9)
那个么事情是怎么发生的呢。请帮我理解。
浏览程序并可视化链表的状态可能会有所帮助:
当执行l = ll()
时,构造函数运行,l
引用该数据结构:
l
↓
┌────────────┐
│ head: None │
└────────────┘
然后l.head = Node(6)
将运行Node
构造函数,然后将从中获得的引用分配给上图中的head
成员。
l
↓
┌────────────┐
│ head: ─┐ │
└────────│───┘
│
▼
┌────────────┐
│ data: 6 │
│ next: None │
└────────────┘
second = Node(2)
也发生了类似的情况,但现在返回的引用被分配给了一个名称,而不是属性:
l
↓
┌────────────┐
│ head: ─┐ │
└────────│───┘
│ second
▼ ↓
┌────────────┐ ┌────────────┐
│ data: 6 │ │ data: 2 │
│ next: None │ │ next: None │
└────────────┘ └────────────┘
使用l.head.next = second
,第一个节点的next
属性获得对第二个节点的引用:
l
↓
┌────────────┐
│ head: ─┐ │
└────────│───┘
│ second
▼ ↓
┌────────────┐ ┌────────────┐
│ data: 6 │ │ data: 2 │
│ next: ─────────►│ next: None │
└────────────┘ └────────────┘
现在进行了更具挑战性的insertEnd(9)
调用。在insertEnd
中,newnode = Node(value)
创建一个新节点,并将其引用分配给本地名称:
l
↓
┌────────────┐
│ head: ─┐ │
└────────│───┘
│ second newNode (local)
▼ ↓ ↓
┌────────────┐ ┌────────────┐ ┌────────────┐
│ data: 6 │ │ data: 2 │ │ data: 9 │
│ next: ─────────►│ next: None │ │ next: None │
└────────────┘ └────────────┘ └────────────┘
另一个本地名称引用了已经在列表中的第一个节点:currentNode = l.head
:
l
↓
┌────────────┐
│ head: ─┐ │
└────────│───┘
│ second newNode (local)
▼ ↓ ↓
┌────────────┐ ┌────────────┐ ┌────────────┐
│ data: 6 │ │ data: 2 │ │ data: 9 │
│ next: ─────────►│ next: None │ │ next: None │
└────────────┘ └────────────┘ └────────────┘
↑
current (local)
然后循环开始。它将进行一次迭代,更新本地名称以获得另一个引用:currentNode = currentNode.next
l
↓
┌────────────┐
│ head: ─┐ │
└────────│───┘
│ second newNode (local)
▼ ↓ ↓
┌────────────┐ ┌────────────┐ ┌────────────┐
│ data: 6 │ │ data: 2 │ │ data: 9 │
│ next: ─────────►│ next: None │ │ next: None │
└────────────┘ └────────────┘ └────────────┘
↑
current (local)
此时,循环条件不再为真,因此循环退出。在这一点上,我们可以确定current
引用了链表中的尾节点。最后,该尾节点得到其next
属性的更新,因此它链接到新节点:currentNode.next = newnode
l
↓
┌────────────┐
│ head: ─┐ │
└────────│───┘
│ second newNode (local)
▼ ↓ ↓
┌────────────┐ ┌────────────┐ ┌────────────┐
│ data: 6 │ │ data: 2 │ │ data: 9 │
│ next: ─────────►│ next: ─────────►│ next: None │
└────────────┘ └────────────┘ └────────────┘
↑
current (local)
insertEnd
函数返回,因此它的所有本地名称都被丢弃,主程序看到:
l
↓
┌────────────┐
│ head: ─┐ │
└────────│───┘
│ second
▼ ↓
┌────────────┐ ┌────────────┐ ┌────────────┐
│ data: 6 │ │ data: 2 │ │ data: 9 │
│ next: ─────────►│ next: ─────────►│ next: None │
└────────────┘ └────────────┘ └────────────┘