I've recently learned how to implement linked list in Python. Can anyone help me to refine my code of implementing methods 'insert()', and 'pop()'.
pop(pos) - remove and return item at position pos.
insert(pos, item) - adds a new item to the list at position pos.
Did I consider all the cases? Thank you in advance!
EDITED: I've add test cases for pop
and insert
class Node:
def __init__(self, data):
'''create a node'''
self.data = data
self.next = None
# LINKED LIST IMPLEMENTATION
class LinkedList:
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def __repr__(self):
'''ll representation
O(n)'''
nodes = []
cur = self.head
while cur:
nodes.append(str(cur.data))
cur = cur.next
nodes.append("None")
return '->'.join(nodes)
def add(self, item):
'''add a new item at the head of ll
O(1)'''
# create a new node for item
newNode = Node(item)
# set newnode to refer to head
newNode.next = self.head
# set newnode to be new head
self.head = newNode
def size(self):
'''return #nodes
O(n)'''
# traverse ll and count nodes
cur = self.head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def search(self, key):
'''search for key in ll'''
# traverse ll to find key
# O(n)
cur = self.head
while cur:
if cur.data == key:
return True
cur = cur.next
return False
def remove(self, key):
'''remove key from ll
O(n)'''
# if ll empty, raise error
if self.head == None:
raise Exception("Linked list is empty!")
# if head holds key, set a new head
if self.head.data == key:
self.head = self.head.next
return
# otherwise, traverse ll for key
prev = None
cur = self.head
while cur:
# key found
if cur.data == key:
prev.next = cur.next
return
# key not found yet, move prev and cur 1 node ahead
prev = cur
cur = cur.next
# cur is None, key not present
raise Exception('Key not present in ll!')
def append(self, item):
'''append an item to the end of ll.
O(n)'''
# create a new node for item, by default node points to None
newNode = Node(item)
# if ll is empty, set head to be new node
if self.head == None:
self.head = newNode
return
# otherwise, traverse the whole ll
cur = self.head
while cur.next:
cur = cur.next
cur.next = newNode
def index(self, key):
'''return idnex of key in ll
O(n)'''
# if ll empty, raise error
if self.head == None:
raise Exception("LL is empty!")
# traverse ll to find key
pos = 0
cur = self.head
while cur:
if cur.data == key:
return pos # found
# else, move to next node
cur = cur.next
pos += 1
# key not present
return -1
def popLastNode(self):
'''remove and return last item of ll.
O(n)'''
# if ll is empty, cant pop
if self.head == None:
raise Exception('ll is empty!')
# only 1 node, set ll to empty
if self.head.next == None:
self.head = None
return
# otherwise, traverse ll and remove last node
cur = self.head
while cur.next.next:
cur = cur.next
lastVal = cur.next.data
cur.next = None
return lastVal
def pop(self, pos=0):
'''remove and return item at pos
O(n)'''
# invalid pos
if pos < 0 or pos >= self.size():
raise IndexError('Index out of range!')
# otherwise, traverse ll to pos
prev = None
cur = self.head
idx = 0 # index of cur node
while idx < pos:
prev, cur = cur, cur.next
# pop at the beginning
if idx == 0:
val = self.head.data
self.head = self.head.next
return val
val = cur.data
prev.next = cur.next
return val
def insert(self, item, pos=0):
'''insert an item at pos.
invalid pos > error
pos == 0, change head'''
# create a new node for item
newNode = Node(item)
# pos == 0, set new head (add method)
if pos == 0:
newNode.next = self.head
self.head = newNode
return
# invalid pos
if pos < 0 or pos >= self.size():
raise IndexError('Index out of range!')
# otherwise, traverse ll
prev = None
cur = self.head # insert between prev and cur
idx = 0
while idx < pos:
prev = cur
cur = cur.next
idx += 1
prev.next = newNode
newNode.next = cur
# TEST CASES
# pop method
l5 = LinkedList()
# l5.pop(-1) - error, index out of range
# l5.pop(0) - error, index out of range
# l5.pop(5) - error, index out range
l5.add(1)
print(l5.pop()) # 1
l5.add(2)
l5.add(3)
l5.add(4)
print(l5)
# print(l5.pop(4)) - error, idx out of range
print(l5.pop(2))
print(l5)
#%%
# insert
l6 = LinkedList()
# l6.insert(2, 1) - error, index out of range
l6.insert(2)
print(l6)
# l6.insert(3, 2) - error, index out of range
# l6.insert(3, 1) - error, index out of range
l6.insert(3)
l6.insert(4, 1)
print(l6)
l6.insert(5, 1)
print(l6)