copied from project 4 to project 5

This commit is contained in:
2026-03-15 16:24:38 -04:00
parent 7c9090f292
commit 511dd6a9db
2 changed files with 232 additions and 0 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"python-envs.defaultEnvManager": "ms-python.python:system"
}

229
Project 5/LinkedList.py Normal file
View File

@@ -0,0 +1,229 @@
"""
This file is duplicated from my Project 4 repo and is identical
"""
######################################
# DCS 229 -- Linked List
# Linked List implementation
# Date: 03/13/2026
# Name: Benjamin Adovasio
# Resources Used: https://docs.python.org/3/tutorial/datastructures.html
##########################################
from __future__ import annotations
# https://docs.python.org/3/tutorial/errors.html#user-defined-exceptions
# Want to define our own custom Exception class...
class EmptyError(Exception):
def __init__(self, message: str) -> None:
super().__init__(message)
self.message = message
class Node[T]:
''' class to implement a single node object in a singly-linked
linked list '''
def __init__(self, data: T):
self.data = data
self.next = None # points to another Node object
def get_data(self) -> T:
return self.data
def set_data(self, value: T) -> None:
self.data = value
def get_next(self) -> Node[T]:
return self.next
def set_next(self, next_node: Node[T]) -> None:
self.next = next_node
class LinkedList[T]:
''' class to implement a singly-linked linked list '''
def __init__(self) -> None:
self.head = None # the head pointer in the linked list
self.size = 0
def __len__(self) -> int:
''' returns the number of nodes in the linked list
Returns:
int - representing the number of nodes in the list
'''
return self.size
def insert_head(self, value: T) -> None:
''' adds the given T-type data value to the front of the linked list
Parameters:
value: a type T data item to be included as the data in the inserted Node
Returns:
nothing
'''
## YOUR CODE HERE ##
new_node = Node(value) # create a new node new_node
new_node.set_next(self.head) # set the new node's next pointer to the current head of the list
self.head = new_node # update the head pointer to point to the new node
self.size += 1 # increase the size of the list by 1
def insert_tail(self, value: T) -> None:
''' adds the given T-type data value to the end of the linked list
Parameters:
value: a type T data item to be included as the data in the inserted Node
Returns:
nothing
'''
## YOUR CODE HERE ##
"""
The insert_tail method creates a new node with the given value and adds it to the end of the linked list. If the list is empty, it sets the head pointer to the new node. Otherwise, it traverses the list until it reaches the last node and updates its next pointer to point to the new node. Finally, it increments the size of the list by 1.
"""
new_node = Node(value) # create a new node new_node
if self.head is None:
self.head = new_node #if the list is empty, set the head pointer to the new node
else: #else go through list until we reach end and set the last node's next pointer to the new node
current = self.head
while current.get_next() is not None:
current = current.get_next()
current.set_next(new_node)
self.size += 1 #increase the size of the list by 1
def remove_head(self) -> T:
''' removes the first Node in the linked list, returning the data item
inside that Node... Remember to handle the special case of an
empty list (what should the head pointers be in that case?)
and remember to update the head pointer when appropriate.
Returns:
a T type data item extracted from the removed Node
Raises:
EmptyError exception if list is empty
'''
# raise an error if list is empty
# https://docs.python.org/3/tutorial/errors.html#user-defined-exceptions
if self.size == 0:
raise EmptyError("Cannot remove from an empy list")
## YOUR CODE HERE ##
removed_node = self.head # store the current head node in a variable removed_node
self.head = self.head.get_next() # update the head pointer to point to the next node in the list (which could be None if there was only one node)
self.size -= 1 #decrease the size of the list by 1
return removed_node.get_data() # return the data item from the removed node
def remove_tail(self) -> T:
''' removes the last Node in the linked list, returning the data item
inside that Node... Remember to handle the special case of an
empty list
Returns:
a T type data item extracted from the removed Node
Raises:
EmptyError exception if list is empty
'''
# raise an error if list is empty
if self.size == 0:
raise EmptyError("Cannot remove from an empy list")
## YOUR CODE HERE ##
"""
If the list has only one node, we can simply remove the head and return its data. Otherwise, we need to traverse the list to find the second-to-last node, update its next pointer to None, and return the data from the last node.
"""
if self.head.get_next() is None: #continue if the list has only one node
removed_data = self.head.get_data() #return the data
self.head = None #set the head to none
self.size -= 1 #decrease the size of the list by 1
return removed_data #return the data from the removed node
current = self.head #start from the head node
while current.get_next().get_next() is not None: #while the next node's next pointer is not None, keep going
current = current.get_next() #move current to the next node
removed_data = current.get_next().get_data()
current.set_next(None)
self.size -= 1 #decrease the size of the list by 1
return removed_data #return the data from the removed node
def __str__(self):
''' returns a str representation of the linked list data
Returns:
an str representation of the linked list, showing head pointer
and data tiems
'''
str_ = "head->"
# start out at the head Node, and walk through Node by Node until we
# reach the end of the linked list (i.e., the ._next entry is None)
ptr_ = self.head
while ptr_ is not None:
str_ += "[" + str(ptr_.get_data()) + "]->"
ptr_ = ptr_.get_next() # move ptr_ to the next Node in the linked list
if self.head != None:
str_ = str_[:-2] # remove trailing "->"
str_ += "<-tail"
return str_
def main():
# create a LinkedList and try out some various adds and removes
ll = LinkedList()
try:
ll.remove_head()
except EmptyError as err:
print(err)
ll.insert_head(8)
assert len(ll) == 1
removed = ll.remove_head()
assert removed == 8
assert len(ll) == 0
ll.insert_tail(6)
ll.insert_tail(7)
ll.insert_tail(5)
print(ll)
assert len(ll) == 3
removed = ll.remove_tail()
assert removed == 5
assert len(ll) == 2
# ADD MORE TESTS
# test inserting multiple at head
ll.insert_head(1)
ll.insert_head(2)
ll.insert_head(3)
assert len(ll) == 5
print(ll)
# test removing head repeatedly
assert ll.remove_head() == 3
assert ll.remove_head() == 2
assert len(ll) == 3
# test removing tail until empty
assert ll.remove_tail() == 7
assert ll.remove_tail() == 6
assert ll.remove_tail() == 1
assert len(ll) == 0
# test removing from empty again
try:
ll.remove_tail()
except EmptyError:
print("Correctly caught empty list error")
if __name__ == "__main__":
main()