I am writing a method to insert a value at a given location in a circular linked list:
def insertCSLL(self,value,location): #Insertion of a node in Singly LL
if self.head is None:
return "The Head refernce is None"
else:
newNode = Node(value)
if location == 0: # insertion at first position
newNode.next = self.head
self.head = newNode
self.tail.next = newNode
In the last line self.tail.next
points to the newNode
Do I also need to write self.tail = newNode
, so to arrive at this?
newNode = Node(value)
if location == 0: # insertion at first position
newNode.next = self.head
self.head = newNode
self.tail.next = newNode
self.tail = newNode # <<<
Is this last line optional?
is this last line optional?
It should not be there as it introduces a bug: it makes self.tail
equal to self.head
which should only happen when the list has fewer than 2 nodes. But since this code is in the else
block, it means the new node is added to a list which already has an element, and then head and tail should not be the same reference.
Not your question, but you should obviously deal with the other cases as well, not only where location
is 0. And in those cases there is a case where you may want to add that assignment. This is the case where location
is equal to the number of nodes that the list has (before the insertion), indicating that the insertion should happen right after the current tail, and then become the tail.
For a circular list it should not be necessary to maintain two references (head and tail). As in a non-empty list it is always supposed to be true that the head is the successor of the tail, you can choose to only maintain a reference to the tail.
Here is an implementation of how that could work:
class Node:
def __init__(self, value, nxt=None):
self.value = value
self.next = nxt or self # Default is a self reference!
class CircularSinglyLinkedList:
def __init__(self):
self.tail = None
def get_at(self, location):
if self.tail:
curr = self.tail.next
for _ in range(location):
curr = curr.next
return curr
def insert(self, value, location=0):
if not self.tail:
self.tail = Node(value)
else:
prev = self.get_at(location - 1) if location else self.tail
# insert node after prev
prev.next = Node(value, prev.next)
# if the node was inserted after the tail (and location was not 0)
# then make the new node the tail
if prev == self.tail and location:
self.tail = prev.next
# Iterator can serve many purposes, like printing
def __iter__(self):
if self.tail:
curr = self.tail.next
while curr is not self.tail:
yield curr.value
curr = curr.next
yield curr.value
Demo run:
lst = CircularSinglyLinkedList()
lst.insert(1)
lst.insert(2)
lst.insert(3)
lst.insert(4)
lst.insert(5, 4)
print(*lst) # 4 3 2 1 5