Explanation about dummy nodes and pointers in linked lists

Question:

I have the following class for a list node:

    def __init__(self, x):
        self.val = x
        self.next = None

If I initialize the lists l and r as follows:

l = ListNode(1)
l.next = ListNode(4)
l.next.next = ListNode(5)

r = ListNode(1)
r.next = ListNode(3)
r.next.next = ListNode(4)

# l: 1->4->5
# r: 1->3->4

and the dummy/current nodes as

dummy = cur = ListNode(0)
# cur = 0
# dummy = 0

when I set

cur.next = l
# cur = 0->1->4->5
# dummy = 0->1->4->5

both lists put l in the second node position, but when I set

cur = cur.next
# cur = 1->4->5
# dummy = 0->1->4->5

only the cur list loses the first node. And then when I set

cur.next = r
# cur = 1->1->3->4
# dummy = 0->1->1->3->4

the cur list attaches the r list at the second position, but the dummy list attaches it at the third position. I would think dummy would look like 0->1->3->4

I figure this is something I’m missing either about pointers in python or linked lists in general. Any explanation would be appreciated!

Asked By: Jess

||

Answers:

The crucial thing here is that when you set a Python variable to an object, it’s a pointer, not a value. So in this code here:

dummy = cur = ListNode(0)
# cur = 0
# dummy = 0

dummy and cur both point to the same object (i.e. the same single-element list). When you append your other list to cur, you’re simultaneously appending it to dummy because it’s the same list.

Box-and-pointer diagram:

dummy
  |
  v
/---
| 0 |
---/
  ^
  |
 cur

When you do this:

cur = cur.next
# cur = 1->4->5
# dummy = 0->1->4->5

you’re not creating a new list, you’re just iterating your cur pointer down the existing list. Both pointers are part of the same list, but dummy points to the first element and cur points to the second element.

Box-and-pointer diagram:

dummy
  |
  v
/---    /---    /---    /---
| 0 |--->| 1 |--->| 4 |--->| 5 |
---/    ---/    ---/    ---/
           ^
           |
          cur

Each time you call ListNode() you’re creating a new node, so if you want to create two nodes with the same value, you need to call the initializer twice:

dummy = ListNode(0)
cur = ListNode(0)
# cur and dummy both have values of 0, but they're different list objects!
dummy
  |
  v
/---
| 0 |
---/


/---
| 0 |
---/
  ^
  |
 cur

Also: I’m not sure if this is what you were getting at when you mentioned "dummy nodes", but note that there is no particular need for a special "dummy node" in your list to signify the end of the list; None serves that purpose just fine (i.e. the end of the list is the one whose next is None).

Answered By: Samwise
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.