I was reading about data structures this evening and I worked out simple singly linked list. The neat thing about this implementation is that a I made it iterable, also. I’d originally wanted to provide a minimal working singly linked list, and then add features and testing with explanations, but it’s been a long day. This example assumes that you’re using Python2.7; version 3 provides a __next__ class method.
Another neat thing about this implementation is that you get Stack and Queue data structures for free. You can turn this into a Stack by deleting the popLast() and addLast() methods, or Queue by deleting the popFirst() and addLast(). If you can manage with the awkward names, then you should be fine.
class SinglyLinkedList:
class Node:
def __init__( self, data, nextNode ):
self.nextNode = nextNode
self.data = data
def __init__( self ):
self.first = None
self.last = None
self.count = 0
self.current = None
def addFirst( self, data ):
if self.count == 0:
self.first = self.Node( data, None )
self.last = self.first
elif self.count > 0:
self.first = self.Node( data, self.first )
self.current= self.first
self.count += 1
def addLast( self, data ):
if self.count == 0:
self.addFirst( data )
elif self.count > 0:
self.last.nextNode = self.Node( data, None )
self.last = self.last.nextNode
self.count += 1
def popLast( self ):
cursor = self.first
if self.count == 0:
raise RuntimeError("Cannot pop from an empty linked list")
elif self.count == 1:
result = cursor.data
self.first = None
self.last = None
self.current = None
else:
for i in range( self.count-2 ):
cursor = cursor.nextNode
result = cursor.nextNode.data
self.last = cursor
self.last.nextNode = None
self.count -= 1
return result
def popFirst( self ):
if self.count == 0:
raise RuntimeError("Cannot pop from an empty linked list")
result = self.first.data
if self.count == 1:
self.first = None
self.last = None
else:
self.first = self.first.nextNode
self.current = self.first
self.count -= 1
return result
def __repr__( self ):
result = ""
if self.count == 0:
return "..."
cursor = self.first
for i in range( self.count ):
result += "{}".format(cursor.data)
cursor = cursor.nextNode
if cursor is not None:
result += " -> "
return result
def __iter__( self ):
# lets Python know this class is iterable
return self
def next( self ):
# provides things iterating over class with next element
if self.current is None:
# allows us to re-iterate
self.current = self.first
raise StopIteration
else:
result = self.current.data
self.current = self.current.nextNode
return result
def __len__( self ):
return self.count
sll = SinglyLinkedList()
sll.addLast("!!")
sll.addFirst("pls")
sll.addFirst("me")
sll.addFirst("halp")
sll.addLast("!!!")
assert sll.count > 0
assert len( sll ) == 5
assert list( sll ) == ["halp","me","pls","!!", "!!!"]
assert sll.popLast() == "!!!"
assert list( sll ) == ["halp","me","pls","!!"]