我有一个单链表 L,并创建一个指向该列表 P 的指针。似乎有时修改 P 会更改实际列表,而其他时候修改 P 对实际列表 L 没有任何作用,只会更改 P 所指向的内容到。
假设我创建一个指向 L 的指针,P = L(在 python 中)。执行类似 P = P.next 的操作会使 L 保持不变,但 P.next = P.next.next 会更改 L。同样,通过修改 P.data 来更改存储在列表中的实际数据实际上会更改 L.data。
为什么会出现这种情况?我觉得我错过了一些关于指针/引用的基本知识。
class Node:
def __init__(self, val):
self.val = val
self.next = None
def addNode(self, val):
root = self
while root.next is not None:
root = root.next
root.next = Node(val)
def iterateLL(self):
root = self
print
while root is not None:
print(str(root.val) + " ", end="")
root = root.next
print()
if __name__ =="__main__":
L = Node(1)
L.addNode(2)
L.addNode(3)
L.addNode(4)
# iterate through list and print:
L.iterateLL()
# changing value of pointer does not affect L
P = L
P = P.next
L.iterateLL() # L is unchanged
# changing "next" value of pointer does affect L
P = L
P.next = P.next.next
L.iterateLL() # now we've skipped node 2
# changing data of pointer does affect L
P = L
P.val = 10
L.iterateLL()
上面的代码执行后输出如下(第一行显示原始链表,第二行显示指针 P 更改后链表未更改,而第三行和第四行显示链表已更改)
1 2 3 4
1 2 3 4
1 3 4
10 3 4
这里发生了什么?为什么改变 P 不会影响 L,但改变 P.next 和 P.val 会影响?如果所有这些操作的行为方式相同,也不会改变指针always更改链表(因此 P = P.next 应该通过删除第一个节点来修改 L),或者never更改链表(因此 P.next = P.next.next 应该保持 L 不变)?
我有一种感觉,这与 L.next 是一个指针有关,就像 P.next 一样。因此修改 P.next 最终会修改 L.next 指向的内容(?)。但我觉得规则对我来说不太清楚。
In most在 Python 中,当你对变量执行赋值时,P
在这种情况下,值P
改变了,但它最初引用的对象没有改变。这是因为 Python 变量只是对象的引用/指针。这是一个例子:
var1 = "test1"
var2 = "test2"
var3 = var1 # var3 = "test1"
var1 = var2 # var1 = "test2"
print(var1) # "test2"
print(var2) # "test2"
print(var3) # "test1"
那么这里发生了什么?我们只是改变这些变量指向的内容,而不是改变底层对象。
现在,在您的情况下,您执行以下操作:
# changing value of pointer does not affect L
P = L
P = P.next
L.iterateLL() # L is unchanged
当你这样做时P = L
and P = P.next
,你只需改变变量的内容P
正在指向。您没有对底层对象进行更改P
指着。让我们想象一下。
Original Configuration:
P = L
P = L.next
然而,当你这样做时
P = L
P.next = P.next.next
L.iterateLL() # we've now skipped node two
您正在更改对象的属性P
正在指向。您正在设置属性P.next
指向P.next.next
。您实际上并没有对底层对象进行更改P.next
原本是指的。通过这样做,该对象P.next
最初指向超出范围并被垃圾收集器清理。
P.next = P.next.next
根据您的代码判断,我认为您在这种情况下的预期行为是删除L
从 LinkedList 中得到一个像“2 3 4”这样的列表。为了实现这一点,应该足以做到L = L.next
。这将导致第一个节点超出范围,垃圾收集器应该清理它。
作为一个快速警告,我在most在某些情况下,赋值不会更改变量所指向的对象。然而,属性有点不同。他们重写了__set__
魔术方法,它允许您使用赋值运算符编辑底层对象。这里的情况并非如此。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)