February 26, 2024
Abstract data type
Concrete data structure
Stack
abstract data typeStack
abstract data typeLIFO
orderLIFO
orderTrue
if storing no items or return False
Stack
wraps a list
in a Python classStack
to give implementation cluesListStack
!ListStack
implements the Stack
ADTListStack
uses a list
called _L
to store data itemsListStack
def 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 ListStack
LIFO
behavior of the ListStack
ListStack
by accessing _L
Stack
insert
call in push
takes \(O(n)\) timepop
call in push
takes \(O(n)\) timeInefficientListStack
def 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 inefficiencyQueue
abstract data typeStack
ADTQueue
abstract data typeTrue
if storing no items or return False
Queue
abstract data type wraps a list
in a Python classQueue
to give implementation cluesListQueueSimple
!ListQueueSimple
implements Queue
ListQueueSimple
uses a list
called _L
to store data itemsListQueueSimple
def 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
Making the Queue
implementation more efficient:
Queue
Queue
Queue
ListQueueFakeDelete
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) == 0
ListQueueFakeDelete
def 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
instanceListQueueSimple
ListQueueSimple
’s?ListQueueFakeDelete
ListQueueFakeDelete
dequeue
methodlist.pop()
in Pythondequeue
dequeue
function is \(O(n)\)self._L = self._L[self._head:]
dequeue
function:
self._head > len(self._L)//2
Stack
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 IndexError
Deque
abstract data typeQueue
Queue
Stack
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
!ListDeque
first
or last
ListDeque
Key question: Can we preserve the features of the Deque
while avoiding the linear time complexity of addfirst
and removefirst
?
Algorithmology