如何解决更改链表中节点的数据不会更改引用同一内存地址的另一个变量的数据
我不知道如何为这篇文章命名。
最初,当我尝试反转链接列表的后半部分时,我在 main
函数中更改原始链接列表时遇到了麻烦,我相信我现在明白了。但是,我现在无法理解在操作链接列表中的数据时发生了什么。我写下了我的代码,但在接近尾声时,我编写了一个单独的函数来解释我对此的思考过程并解释为什么我无法理解。
class Node:
def __init__(self,value,next=None):
self.value = value
self.next = next
def find_middle(head):
slow,fast = head,head
while fast is not None and fast.next is not None:
slow = slow.next
fast = fast.next.next
return slow
def reverse_second_half(head):
middle = find_middle(head)
second_half_reversed = reverse(middle,head)
return '\nfinished'
def reverse(head,original_head):
prev = None
iteration = 1
while head is not None:
pointer = original_head
print('\noriginal list iteration = ' + str(iteration) + '\n')
while pointer is not None:
print('current pointer value = ' + str(pointer.value))
pointer = pointer.next
iteration += 1
next = head.next
head.next = prev
prev = head
head = next
return prev
def main():
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
head.next.next.next = Node(4)
head.next.next.next.next = Node(5)
print(reverse_second_half(head))
main()
在 main
中,我调用 reverse_second_half
,后者调用 find_middle
和 reverse
函数。在找到链接列表的中间之后,我从在 find_middle
中找到的中间节点开始反转链接列表的后半部分。
我将其传递给反向,但我也将“原始列表”作为第二个参数传递。我这样做是因为我想看看一旦反转开始执行,原始列表是如何改变的。
我看到,对于第一次迭代,但在发生任何逆转之前,原始链表及其所有值都会被打印出来,从而在控制台中打印出以下内容。
original list iteration = 1
current pointer value = 1
current pointer value = 2
current pointer value = 3
current pointer value = 4
current pointer value = 5
对于第二次迭代...
original list iteration = 2
current pointer value = 1
current pointer value = 2
current pointer value = 3
依此类推......(每隔一次迭代都会打印出第二次迭代给出的结果作为输出)。
所以我知道我操作的不是列表的副本,而是同一个列表本身。
根据我的理解我们可以看到,在任何逆转发生之前的第一次迭代中的原始链表是
然后一步一步地进行第一次迭代
在这里我看到原始列表已更改,不再包含后半部分。我可以在这里看到我没有某个列表的单独副本,但是我们正在使用相同的列表本身,因为我们只是将变量指向内存地址。这对我来说似乎很奇怪,因为当我这样做时
next = head.next
在第一次迭代期间,从上表中我们看到 next 指向值为 4 的节点,但是在下一行
head.next = prev
其中 prev == None
应该将列表更改为
1 -> 2 -> 3 -> None
但是如果 next
指向 head.next
并且 head.next
被更改为 None
怎么办
head = next
获取列表4 -> 5
def change_value_in_linked_list(head):
middle = find_middle(head)
middle.value = 'oops'
while head is not None and head.next is not middle:
head = head.next
print(head.next.value)
print(middle.value)
return '\nfinished'
如果我们使用其余代码运行上述代码并在 main 中调用此函数而不调用 reverse_second_half
仅用于测试目的,我会看到 head.next.value
和 middle.value
包含相同的数据将 middle.value
更改为字符串 oops
后。我的理解是中间点指向一个内存位置,当我们改变它的数据并试图通过遍历链表来找到相同的内存位置时,我们看到现在在原始链表中我们找到了改变的数据
1 -> 2 -> 'oops' -> 4 -> 5
但是,如果我将函数改为这样
def change_value_in_linked_list(head):
middle = find_middle(head)
middle.value = 'oops'
while head is not None and head.next is not middle:
head = head.next
head.next = None
print(head.next)
print(middle.value)
return '\nfinished'
更改 middle.value = 'oops'
后,我假设 head.next.value
和 middle.value
是“哎呀”,根据我们之前看到的内容,这是正确的。但是,我现在添加了
head.next = None
我再次假设 head.next 指向一个内存位置,我们正在将该数据更改为 None
。 middle
指向同一个内存位置,但是当打印出包含在 head.next
和 middle
中的数据时,中间仍然包含一个值为 oops
和 head.next
的有效节点现在是None
也许我遗漏了一些明显的东西,但这让我很失望。就好像参数正在声明更改由不同指针引用的内存位置中的数据将数据更改为每个指针的更改数据,因为这些指针没有被分配该数据,而是仅指向内存位置,但是通过执行 head.next = None
并看到 head.next
和 middle
(指向同一内存位置的两个指针)包含不同的数据,与此参数相矛盾。
解决方法
如果我正确理解了您的问题,我认为您的困惑在于如何使用 =
将变量/引用绑定到对象。也许这些图形会有所帮助:
您的链表已被切断。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。