Reputation: 123
I'm learning Python coming from C++ and I'm not sure why my insert method in class LinkedList is not working. I'm expecting my Header node to be linked to my Tail Node, but I'm not getting the expected behavior.
class Node:
value = None
nextNode = None
def __init__(self, value=None):
self.value = value
self.nextNode = None
class LinkedList:
head = Node()
tail = Node()
def __init__(self):
self.head = None
self.tail = Node()
#insert a node method
def insert(self, value):
#if new list
if self.head == None:
newNode = Node(value)
self.head = newNode
newNode.nextNode = self.tail
else:
newNode = Node(value)
self.tail.nextNode = newNode
self.tail = newNode
newNode.nextNode = self.head
list1 = LinkedList()
list1.insert(23)
list1.insert(50)
print(list1.head.nextNode.value) #Expect this to be 50, but this returns None
Upvotes: 0
Views: 3294
Reputation: 81
You don't need to have an elif or the tail.
class Node:
value = None
nextNode = None
def __init__(self, value=None):
self.value = value
self.nextNode = None
class LinkedList:
head = Node()
def __init__(self):
self.head = None
#insert a node method
def insert(self, value):
#if new list
newNode = Node(value)
if not self.head:
self.head = newNode
else:
#save head's current position
temp = self.head
#move head's position until you find a None value for
#nextNode
while(temp.nextNode):
temp = temp.nextNode
#set the none value to the new node
temp.nextNode = newNode
list1 = LinkedList()
list1.insert(23)
list1.insert(50)
list1.insert(50)
list1.insert(70)
print(list1.head.value)
#23
print(list1.head.nextNode.value)
#50
print(list1.head.nextNode.nextNode.value)
#50
print(list1.head.nextNode.nextNode.nextNode.value)
#70
Upvotes: 0
Reputation: 3031
If you are trying to insert a new node as a tail then try this:
class Node:
def __init__(self, value=None):
self.value = value
self.nextNode = None
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
def insert(self, value):
new_node = Node(value)
if not self.head:
self.head = new_node
elif self.tail:
self.tail.nextNode = new_node
self.tail = new_node
else:
self.head.nextNode = new_node
self.tail = new_node
list1 = LinkedList()
list1.insert(23)
list1.insert(50)
list1.insert(40)
list1.insert(99)
node = list1.head
print('(head)', end=' -> ')
while node:
print(node.value, end=' -> ')
node = node.nextNode
print('(tail)')
(head) -> 23 -> 50 -> 40 -> 99 -> (tail)
No need to use class variables.
Upvotes: 2
Reputation: 532033
The class is much simpler with a sentinel, but the head should be the sentinel.
class Node:
def __init__(self, value):
self.value = value
self.next = None
class LinkedList:
def __init__(self):
self.head = Node(0) # Store the length, or any other metadata you like
self.tail = self.head # The tail is just the last item.
# the list is empty when the head and the tail are the same
# node (namely, the sentinel)
def is_empty(self):
return self.tail is self.head
def insert(self, value):
"""Add a value to the end of the list"""
new_node = Node(value)
self.tail.next = new_node # Append the node
self.tail = new_node # Advance the tail
self.head.value += 1 # Update the length
And that's all you need. The list maintains two invariants: the head always refers to a sentinel node, and the tail always refers to the last element of the list. Appending to the list just means appending a node after the tail, then updating the tail.
The purpose of the head is to provide an entry point for iterating over the list. The tail is a convenience, to make appending to the end of the list an O(1) operation, rather than having to spend O(n) time iterating from the head to find the last node.
A few exercises:
LinkedList.__len__
, so you can retrieve the length of a list with len(ll)
insert
should really be called append
. Write a "real" insert
method that takes a position to indicate where the new node should be inserted. (ll.insert(0, x)
would create a new first element, and ll.insert(n, x)
would insert a new element after the n-1
element.)LinkedList.delete
to delete an element at the specified position. ll.delete(0)
would remove the first element of ll
. Note that this should never remove the sentinel, i.e., it's a no-op if ll.is_empty()
returns True
.Upvotes: 2