You should do val = val.next instead of val.next = val.next.next. The way you're doing it, the list will be truncated to a single element when you call count_length. Because you do count_length at the top of kth_to_last, by the time you get around to walking your list (where your 'hi' is), the list has already been reduced to a single node.
Remember, a linked list is a structure where each node's next property is a pointer to the next node. Your code is modifying the value of next, which is changing the structure of your linked list.
When you process a linked list (in count_length, or in kth_to_last), what you want to do is point yourself at each node in turn. You're not trying to modify the nodes themselves, so you won't assign to their value or next attributes. The way to do this is to change what your pointer (val) is pointing at, and the thing that you want it to point at next is the next node along. Therefore:
val = ll.head
while val is not None:
# do something with val here
val = val.next
Answer from wildwilhelm on Stack OverflowI was trying the Merge Two Sorted Lists question from Leetcode and had a pretty fundamental doubt. This is the solution of the code in Python:
def mergeTwoLists(self, list1, list2):
dummy = ListNode()
tail = dummy
while list1 and list2:
if list1.val < list2.val:
tail.next = list1
list1 = list1.next
else:
tail.next = list2
list2 = list2.next
tail = tail.next
if list1:
tail.next = list1
elif list2:
tail.next = list2
return dummy.next
Here, we are returning dummy.next as a representation of the final merged linked list but I thought that the next attribute pointed to only the next node? My understanding was that we would need to return tail since that represents the list node as a whole?
python - Setting a next value for a linkedlist function - Stack Overflow
iterator - implementing __next__() in python linked list - Stack Overflow
linked list iterator python - Stack Overflow
Can somebody explain linked lists in python I'm struggling so bad :(
You're doing way more work than you have to. Once you've implemented __iter__, the rest falls into place. You can use it to implement pretty much all your other functions, like get_node, __str__ or __repr__, etc.
class Node:
def __init__(self, value):
self.value = value
self.next = None
def __str__(self):
return str(self.value)
class LinkedList:
def __init__(self):
self.head = None
def add(self, value):
if self.head is None:
self.head = Node(value)
else:
for cursor in self:
pass
cursor.next = Node(value)
return self
def get_node(self, node_index):
for index, node in enumerate(self):
if index == node_index:
break
else:
return None
return node
def __str__(self):
return " -> ".join(map(str, self))
def __iter__(self):
cursor = self.head
while cursor is not None:
yield cursor
cursor = cursor.next
ll = LinkedList().add(1).add(2).add(3)
print(ll)
for node_index in 0, 1, 2, 3:
print("The node at index {} is {}".format(node_index, ll.get_node(node_index)))
Output:
1 -> 2 -> 3
The node at index 0 is 1
The node at index 1 is 2
The node at index 2 is 3
The node at index 3 is None
>>>
ThisgetNode()also works:
def getNode(self,loc):
it = iter(self)
for i in range(loc):
next(it)
return next(it)
Just as mentioned by @abarnert , you always need a __iter__ method for the iterator class.
class LinkedListIterator:
def __init__(self, head):
self.current = head
def __iter__(self):
return self
def __next__(self):
if not self.current:
raise StopIteration
else:
item = self.current.get_data()
self.current = self.current.get_next()
return item
class LinkedList:
def __init__(self):
self.head = None
def __iter__(self):
return LinkedListIterator(self.head)
def add(self, item):
new_node = Node(item)
new_node.set_next(self.head)
self.head = new_node
Now that your class is iterable, you can use "for...in" loop:
test_list = LinkedList()
test_list.add(1)
test_list.add(2)
test_list.add(3)
for item in test_list:
print(item)
Please check the tutorial here.
You can use the yield keyword to make a generator so you dont have to implement __next__()
class LinkedList:
def __init__(self):
self.head = None
def __iter__(self):
curNode = self.head
while curNode:
yield curNode.value
curNode = curNode.nextNode
def add(self, item):
new_node = Node(item)
new_node.set_next(self.head)
self.head = new_node
And in your print_iterator_explicit function you can do it like this
def print_iterator_explicit(items):
iterator = iter(ll)
while True:
try:
print(next(iterator))
except StopIteration:
break
Check out this link for more information on iterators and generators: Iterators and generators
A little side note: your head variable is behaving like a tail. In a linked list the first node is called the head and the last is called the tail