Reputation: 199
I am really confused by the Python linked list data structure used in Leetcode. I am not sure if the problem is caused by the specific ListNode structure created by Leetcode, or I have some misunderstanding about Python. For example, the following piece of code is simple and self-explained:
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
def main():
# Instantiate a linked list 1 -> 2 -> 3
a = ListNode(1)
b = ListNode(2)
c = ListNode(3)
a.next = b
b.next = c
print(a) # a is 1 -> 2 -> 3
b.next = None
print(a) # a is 1 -> 2
b = None
print(a) # a is still 1 -> 2, why changing b doesn't change a, but changing b.next changes a???
Suppose I have a linked list a -> b -> c. When I set b.next = None
, a.next.next = None
. However, the thing that confuses me is that, when I set b = None
, a.next
doesn't become None
.What's the difference between operating b
and b.next
, why they have different influence on a
?
Upvotes: 1
Views: 1782
Reputation: 71574
Drawing diagrams helps. Here's your linked list:
[ ]
|
v
[ ]
|
V
[ ]
|
V
None
Each arrow leading from a box represents the next
attribute of that node.
Here are the three variables a
, b
, and c
:
[ ] <-- a
|
v
[ ] <-- b
|
V
[ ] <-- c
|
V
None
Each of these variables also points to a particular node.
If you say b.next = None
, the next
attribute of the node referenced by b
is modified, like this:
[ ] <-- a
|
v
None <-- [ ] <-- b
[ ] <-- c
|
V
None
This modifies the structure of the list. If you just set b
itself to a different value, though, this is what happens:
[ ] <-- a
|
v
None <-- [ ] b --> None
[ ] <-- c
|
V
None
You changed b
, but the node that b
used to point to stays right where it was. Note that this is similar to how the c
node continued to exist even after you set b.next = None
.
Upvotes: 5
Reputation: 532538
a
is a reference to ListNode(1)
. There are two references to ListNode(2)
: the one stored in ListNode(1)
, referenced as a.next
, and one in b
.
Think of these references as arrows.
When you make the assignment b = None
, you simply removing the arrow from b
to ListNode(2)
and replacing it with an arrow from b
to None
. This has no effect on the arrow from ListNode(1)
to ListNode(2)
.
If you were instead to make a change to, say, ListNode(3)
, then that change would be visible from all three references to it: a.next.next
, b.next
, and c
.
Note that an assignment like b.next = ...
is very different from b = ...
. The latter is a "true" assignment, while the former is special syntax for a function call like setattr(b, 'next', ...)
. It modifies some object (specifically, the value of once of its attributes) in place, rather than just making a name point to something else.
Upvotes: 1
Reputation: 1815
Python doesn't have double pointers e.g. **x
b.next = c
print(a) # a is 1 -> 2 -> 3
b.next = None
E.g. in above, it doesn't mean c is None
When a.next
is b
, if you change a.next.next
you are effectively changing b.next
But if you change a.next
to None
, it will not set b
to None
Edit:
Also when you set b = None
but a.next
still points ListNode(2)
Upvotes: 1