28 KiB
28 KiB
In [1]:
# implementation of Node abstraction
class Node:
def __init__(self):
self.item = None # an item
self.next = None # a nodeIn [50]:
# initialize 3 nodes
first = Node()
second = Node()
third = Node()
# add content to the node
first.item = "to" # first node
second.item = "be" # second node
third.item = "or" # third node
# building the linked list
first.next = second
second.next = third
# iterate through this linked list and print the items
node = first
while node is not None:
print(node.item)
node = node.next
del node # delete the temporary nodeto be or
In [3]:
from typing import TypeVar
Item = TypeVar('Item') # don't worry about this, it makes code more readable
class Bag:
# define the constructor with 2 private attributes
def __init__(self) -> None:
self.__N = 0 # number of items - private
self.__first = None # point to first item in the bag - private
# add an item to bag
def add(self, item: Item) -> None:
oldFirst = self.__first
self.__first = self.Node() # create a new node
self.__first.item = item # add content to that node
self.__first.next = oldFirst # create a reference to next node
self.__N += 1 # increment the size of bag by 1
# nested class Node inside class Bag
class Node:
def __init__(self) -> None:
self.item = None
self.next = None
# method to check if bag is empty
def isEmpty(self) -> bool:
return self.__N == 0
# method to return the size of bag
def __len__(self) -> int:
return self.__N
# print the content of the bag
def __str__(self) -> str:
output_str = "["
self.__iter_node = self.__first
while True:
if self.__iter_node is not None:
output_str += f'{self.__iter_node.item}'
self.__iter_node = self.__iter_node.next
if self.__iter_node is not None:
output_str += ','
else:
break
output_str += ']'
return output_str
# The 2 methods below make the objects iterable
def __iter__(self):
self.__iter_node = self.__first
return self
def __next__(self):
if self.__iter_node is not None:
x = self.__iter_node.item
self.__iter_node = self.__iter_node.next
return x
else:
raise StopIteration
In [52]:
# create a variable of type Bag
bag = Bag()
print(f'The bag after initialization is {bag}')
# check if the bag is empty
print(f"bag is empty: {bag.isEmpty()} \n")
# let's add some items to this bag. Items could be of any data type
bag.add("University of Arkansas")
bag.add(1871)
bag.add("Fayetteville")
# print the content of bag
print(f"The size of the bag after adding is {len(bag)}") # thanks to __len__()
print('The items in the bag after adding are')
print(bag) # thanks to __str__()
# iterate through the bags and print each item
print("\nIterate through this bag")
for item in bag: # thanks to __iter__ and __next__
print(item, end=' ')The bag after initialization is [] bag is empty: True The size of the bag after adding is 3 The items in the bag after adding are [Fayetteville,1871,University of Arkansas] Iterate through this bag Fayetteville 1871 University of Arkansas
In [22]:
# Write class definition of queue below this line
class Queue:
head: Node = None
def enqueue(self, item: Item) -> None:
if not self.head:
self.head = Node()
self.head.item = item
return None
next: Node | None = self.head.next
if not next:
self.head.next = Node()
self.head.next.item = item
return None
while next:
if not next.next:
next.next = Node()
next.next.item = item
return None
next = next.next
def dequeue(self) -> Item:
item = self.head.item
self.head = self.head.next
return item
def isEmpty(self) -> bool:
return not self.head
def peek(self) -> Item | None:
return self.head.item if self.head else None
def __len__(self) -> int:
l = 0
for i in self:
l += 1
return l
def __str__(self) -> str:
s = "["
for item in self:
s += f'{str(item)}, '
if len(self) > 0:
s = s[:-2]
s += "]"
return s
def __iter__(self):
self.__iter_node = self.head
return self
def __next__(self):
if self.__iter_node is not None:
x = self.__iter_node.item
self.__iter_node = self.__iter_node.next
return x
else:
raise StopIteration
In [23]:
# initializing queue
queue = Queue()
print(f'The queue after initialization is {queue}')
assert(queue.isEmpty() == True) # check if isEmpty works properly
# add the items to queue
for i in range(5):
queue.enqueue(i)
print(f'The queue after enqueue is {queue}')
assert(queue.isEmpty() == False) # check if isEmpty works properly
assert(len(queue) == 5) # check if __len__ works properly
# Peek at the front item
front_item = queue.peek()
assert(front_item == 0) #check if peek is working properlyThe queue after initialization is [] The queue after enqueue is [0, 1, 2, 3, 4]
In [24]:
# dequeue the queue
print("Dequeue the queue")
while len(queue) > 0:
item = queue.dequeue()
print(f'item dequeued from queue: {item}')
print(f'queue: {queue}')
print(f'length of queue: {len(queue)}')
assert(queue.isEmpty() == True)
# enqueue the queue
queue.enqueue(5)
print(f"\nQueue after enqueue: {queue}")
print(f"Length of queue: {len(queue)}")Dequeue the queue item dequeued from queue: 0 queue: [1, 2, 3, 4] length of queue: 4 item dequeued from queue: 1 queue: [2, 3, 4] length of queue: 3 item dequeued from queue: 2 queue: [3, 4] length of queue: 2 item dequeued from queue: 3 queue: [4] length of queue: 1 item dequeued from queue: 4 queue: [] length of queue: 0 Queue after enqueue: [5] Length of queue: 1
In [35]:
# Write class definition of stack below this line
class Stack:
items: list[Item] = []
head: Node = None
def push(self, item: Item) -> None:
if not self.head:
self.head = Node()
self.head.item = item
return None
next: Node | None = self.head.next
if not next:
self.head.next = Node()
self.head.next.item = item
return None
while next:
if not next.next:
next.next = Node()
next.next.item = item
return None
next = next.next
def pop(self) -> Item:
node = self.head
last = None
while node.next:
last = node
node = node.next
if not last:
self.head = None
else:
last.next = None
return node.item
def isEmpty(self) -> bool:
return not self.head
def peek(self) -> Item:
node = None
for i in self:
node = i
return node
def __len__(self) -> int:
l = 0
for i in self:
l += 1
return l
def __str__(self) -> str:
s = "["
for item in self:
s += f'{str(item)}, '
if len(self) > 0:
s = s[:-2]
s += "]"
return s
def __iter__(self):
self.__iter_node = self.head
return self
def __next__(self):
if self.__iter_node is not None:
x = self.__iter_node.item
self.__iter_node = self.__iter_node.next
return x
else:
raise StopIteration
In [36]:
# initializing stack
stack = Stack()
print(f'The stack after initialization is {stack}')
assert(stack.isEmpty() == True) # check if isEmpty works properly
# add the items to stack
for i in range(5):
stack.push(i)
print(f'The stack after push is {stack}')
assert(stack.isEmpty() == False) # check if isEmpty works properly
assert(len(stack) == 5) # check if __len__ works properly
#check if peek is working properly
top_item = stack.peek()
assert(top_item==4)The stack after initialization is [] The stack after push is [0, 1, 2, 3, 4]
In [37]:
# pop the stack
print("Pop the stack")
while len(stack) > 0:
item = stack.pop()
print(f'item dequeued from stack: {item}')
print(f'stack: {stack}')
print(f'length of stack: {len(stack)}')
assert(stack.isEmpty() == True)
# enqueue the queue
stack.push(5)
print(f"\nstack after push: {stack}")
print(f"length of stack: {len(stack)}")Pop the stack item dequeued from stack: 4 stack: [0, 1, 2, 3] length of stack: 4 item dequeued from stack: 3 stack: [0, 1, 2] length of stack: 3 item dequeued from stack: 2 stack: [0, 1] length of stack: 2 item dequeued from stack: 1 stack: [0] length of stack: 1 item dequeued from stack: 0 stack: [] length of stack: 0 stack after push: [5] length of stack: 1
In [38]:
class BrowserHistory:
def __init__(self, homepage: str):
self.current_page = homepage
# create a backward stack
self.backward = Stack()
# create a forward stack
self.forward_h = Stack()
def visit(self, url: str) -> None:
# function to visit a new page, updating the history accordingly.
self.backward.push(self.current_page)
self.current_page = url
def back(self, steps: int) -> str:
# function to oves back a specified number of steps in the browsing history.
for i in range(steps):
if not self.backward.isEmpty():
self.forward_h.push(self.current_page)
self.current_page = self.backward.pop()
def forward(self, steps: int) -> str:
# function to moves forward a specified number of steps in the browsing history.
for i in range(steps):
if not self.forward_h.isEmpty():
self.backward.push(self.current_page)
self.current_page = self.forward_h.pop()
def current(self) -> str:
# function to get URL of the current active page
return self.current_page
In [39]:
history = BrowserHistory("uark-aicv.github.io")
history.visit("uark-aicv.github.io/team")
history.visit("uark-aicv.github.io/research")
history.visit("uark-aicv.github.io/publications")
history.visit("uark-aicv.github.io/contact")
assert(history.current()=='uark-aicv.github.io/contact')
In [40]:
history.back(2)
assert(history.current()=='uark-aicv.github.io/research')In [41]:
history.forward(1)
assert(history.current()=='uark-aicv.github.io/publications')