February 24, 2025
Abstract data type
Concrete data structure
InefficientListStackRobustStackListQueueSimpleListQueueFakeDeleteStack abstract data typeStack abstract data typeLIFO orderLIFO orderTrue if storing no items or return FalseStack wraps a list in a Python classStack to give implementation cluesListStack!ListStack implements the Stack ADTListStack uses a list called _L to store data itemsListStackdef manipulate_stack():
stack = ListStack()
stack.push('umbrella')
stack.push('backpack')
stack.push('sandals')
print("Stack contents after push operations: ", [item for item in stack._L])
stack.pop()
print("Stack contents after pop operation: ", [item for item in stack._L])
manipulate_stack()Stack contents after push operations: ['umbrella', 'backpack', 'sandals']
Stack contents after pop operation: ['umbrella', 'backpack']
manipulate_stack function creates a ListStackLIFO behavior of the ListStackListStack by accessing _LListStack!Stackinsert call in push takes \(O(n)\) timepop call in push takes \(O(n)\) timeInefficientListStack(ListStack)?Creating an inheritance hierarchy in Python
InefficientListStack(ListStack):
ListStack class!InefficientListStack is a subclass of ListStackInefficientListStack is a subclass of ListStackInefficientListStack to reuse ListStack methodsInefficientListStack can override methods in ListStackInefficientListStack can add new methods to ListStackInefficientListStack can add new attributes to ListStackInefficientListStack can call methods from ListStackInefficientListStackdef manipulate_stack():
stack = InefficientListStack()
stack.push('umbrella')
stack.push('backpack')
stack.push('sandals')
print("Stack contents after push operations: ", [item for item in stack._L])
stack.pop()
print("Stack contents after pop operation: ", [item for item in stack._L])
manipulate_stack()Stack contents after push operations: ['sandals', 'backpack', 'umbrella']
Stack contents after pop operation: ['backpack', 'umbrella']
InefficientListStack instanceListStack but with inefficiencyInefficientListStack!Queue abstract data typeStack ADTQueue abstract data typeTrue if storing no items or return FalseQueue abstract data type wraps a list in a Python classQueue to give implementation cluesListQueueSimple!ListQueueSimple implements QueueListQueueSimple uses a list called _L to store data itemsListQueueSimpledef manipulate_queue():
queue = ListQueueSimple()
queue.enqueue('umbrella')
queue.enqueue('backpack')
queue.enqueue('sandals')
print("Queue contents after enqueue operations: ", [item for item in queue._L])
queue.dequeue()
print("Queue contents after dequeue operation: ", [item for item in queue._L])
manipulate_queue()Queue contents after enqueue operations: ['umbrella', 'backpack', 'sandals']
Queue contents after dequeue operation: ['backpack', 'sandals']
ListQueueSimple instanceListStack?FIFO and LIFO disciplines?Queue implementation is inefficient because it calls pop(0)!Calling pop(0) takes \(O(n)\) time due to the item shifting
Either approach is inefficient for a Queue implementation
Okay, let’s make the Queue faster!
Making the Queue implementation more efficient:
QueueQueueQueueListQueueFakeDelete uses an indexclass ListQueueFakeDelete:
def __init__(self):
self._head = 0
self._L = []
def enqueue(self, item):
self._L.append(item)
def peek(self):
return self._L[self._head]
def dequeue(self):
item = self.peek()
self._head += 1
return item
def __len__(self):
return len(self._L) - self._head
def isempty(self):
return len(self) == 0ListQueueFakeDeletedef manipulate_queue():
queue = ListQueueFakeDelete()
queue.enqueue('umbrella')
queue.enqueue('backpack')
queue.enqueue('sandals')
print("Queue contents after enqueue operations: ", [item for item in queue._L])
queue.dequeue()
print("Queue contents after dequeue operation: ", [item for item in queue._L])
manipulate_queue()Queue contents after enqueue operations: ['umbrella', 'backpack', 'sandals']
Queue contents after dequeue operation: ['umbrella', 'backpack', 'sandals']
ListQueueFakeDelete instanceListQueueSimpleListQueueSimple’s?class ListQueueFakeDeleteWithDisplay:
def __init__(self):
self._head = 0
self._L = []
def enqueue(self, item):
self._L.append(item)
def peek(self):
return self._L[self._head]
def dequeue(self):
item = self.peek()
self._head += 1
return item
def __len__(self):
return len(self._L) - self._head
def isempty(self):
return len(self) == 0
def __str__(self):
return str(self._L[self._head:])ListQueueFakeDeleteWithDisplay’s new __str__ work as expected?def manipulate_queue_enhanced_display():
queue = ListQueueFakeDeleteWithDisplay()
queue.enqueue('umbrella')
queue.enqueue('backpack')
queue.enqueue('sandals')
print("Queue contents after enqueue operations: ", queue)
queue.dequeue()
print("Queue contents after dequeue operation: ", queue)
manipulate_queue_enhanced_display()Queue contents after enqueue operations: ['umbrella', 'backpack', 'sandals']
Queue contents after dequeue operation: ['backpack', 'sandals']
Queue__str__ method to display the QueueListQueueFakeDeleteListQueueFakeDeletedequeue methodlist.pop() in Pythondequeuedequeue function is \(O(n)\)self._L = self._L[self._head:]dequeue function:
self._head > len(self._L)//2Stack and Queue implementationsraise an Exception to signal an errorException can be “caught” or it can lead to a crashStack with exception handlingclass RobustStack(ListStack):
def pop(self):
try:
return self._L.pop()
except IndexError:
raise RuntimeError("pop from empty stack")
s = RobustStack()
s.push(5)
s.pop()
# un-comment the next line to see a crash!
# s.pop()5
pop is called on an empty stackpop method can raise an IndexError on empty stacktry and except block to catch the IndexErrorDeque abstract data typeQueueQueueStack and Queue ADTs!Deque abstract data typeitem to the front of the dequeitem to the end of the dequeDeque wraps a list in a Python classDeque to give implementation cluesListDeque!ListDequefirst or lastListDequeDeque while avoiding the linear time complexity of addfirst and removefirst?
Stack, Queue, and Dequepush, pop, peekenqueue, dequeue, peekaddfirst, addlast, removefirst, removelastStack, Queue, and Deque
ListStack, InefficientListStack, RobustStackListQueueSimple, ListQueueFakeDelete, ListQueueListDequeAlgorithmology