我有一个单链表,L,并创建一个指向这个列表p的指针。似乎有时修改p会改变实际的列表,而其他时候修改p不会改变实际的列表L,只会改变p所指向的内容。你知道吗
假设我创建了一个指向L的指针,p=L(在python中)。做类似于P=P.next的事情会使L保持不变,但是P.next=P。下一个。下一个类似地,通过修改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会影响L?如果所有这些操作都以相同的方式执行,那么改变指针是否总是改变链表(因此P=P.next应该通过去掉第一个节点来修改L),或者从不改变链表(因此P.next=P。下一个。下一个我应该保持原样吗?你知道吗
我有一种感觉,这与L.next是指针这一事实有关,就像p.next一样。所以修改P.next的结果就是修改L.next指向的(?)。但我觉得规则对我来说并不清楚。你知道吗
你写道
但是,您没有更改下一个值。您可以从
P.next
读取。P.next
在作业的右侧。为了更改P.next
,P.next
必须位于赋值运算符(=
)的左侧然后你写:
此时
P.next
位于赋值运算符(=
)的左侧。因此,你实际上改变了它。你知道吗在Python中的大多数情况下,当您对变量执行赋值时,
P
在本例中,P
的值会更改,但它最初引用的对象不会更改。这是因为Python变量只是对对象的引用/指针。举个例子:那么这里发生了什么?我们只是在改变这些变量所指向的东西,而不是改变底层对象。你知道吗
现在,在您的情况下,您可以执行以下操作:
当您执行
P = L
和P = P.next
时,您只需更改变量P
所指向的内容。您没有对P
指向的基础对象进行更改。让我们想象一下。你知道吗原始配置:
但是,当你这么做的时候
您正在更改
P
所指向的对象的属性。您正在将属性P.next
设置为指向P.next.next
。实际上,您并没有对P.next
最初指向的基础对象进行更改。通过这样做,P.next
最初指向的对象将超出范围,并由垃圾收集器清理。你知道吗根据您的代码判断,我假设您在本例中的预期行为是从LinkedList中删除
L
,最后得到一个类似“2 3 4”的列表。要做到这一点,做L = L.next
就足够了。这将导致第一个节点超出作用域,垃圾收集器应该清理它。你知道吗作为一个简短的警告,我提到在大多数情况下,赋值不会更改变量所指向的对象。但是,属性有点不同。它们重写
__set__
魔术方法,该方法允许您使用赋值操作符编辑基础对象。这里不是这样。你知道吗相关问题 更多 >
编程相关推荐