From e1ef33204a18ac00b13c35019bd727cc5ae4bf2f Mon Sep 17 00:00:00 2001 From: JanefrancessC Date: Tue, 30 Jun 2026 00:38:07 +0100 Subject: [PATCH 1/2] feat: implement O(1) push_head, pop_tail, and remove handle functions --- Sprint-2/implement_linked_list/linked_list.py | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index e69de29..8375940 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -0,0 +1,108 @@ +class Node: + """ + A node in a double linked list. + + Each node supports a data, previous, and next + - data: the value + - previous: pointer to the previous node + - next: pointer to the next node + """ + + def __init__(self, data): + self.data = data + self.previous = None + self.next = None + +class LinkedList: + """ + Double Linked List + + Supports O(1) operations on insertion at head, removal from tail, and removal from arbitrary node + """ + def __init__(self): + # Head points to the first node in the list + self.head = None + + # Tail points to the last node in the list + self.tail = None + + def is_empty(self): + """Returns True if the list contains no nodes.""" + return self.head is None + + def push_head(self, data): + """ + Insert a new node at the head of the list. + + Time Complexity: O(1) + + Returns: + Node: reference to the inserted node (handle for later removal) + """ + node = Node(data) + + if self.is_empty(): + # If list is empty, head and tail both point to new node + self.head = node + self.tail = node + else: + # Link new node before current head + node.next = self.head + self.head.previous = node + + # Update head pointer + self.head = node + + return node + + def pop_tail(self): + """ + Remove and return the value at the tail of the list. + + Time Complexity: O(1) + + Raises: + ValueError: if the list is empty + """ + + if self.is_empty(): + raise ValueError("List is empty.") + + # store value before removing node + value = self.tail.data + + if self.head == self.tail: + # Only one element in the list + self.head = None + self.tail = None + + else: + # Move tail pointer backwards + self.tail = self.tail.previous + + # Disconnect old tail node + self.tail.next = None + + return value + + def remove(self, node): + """ + Remove a node from the list using its reference. + + Time Complexity: O(1) + + Args: + node (Node): the node to remove + """ + if node.previous: + node.previous.next = node.next + else: + self.head = node.next + + if node.next: + node.next.previous = node.previous + else: + self.tail = node.previous + + node.previous = None + node.next = None From d4ba1224ff79c8228ee4149cafaba27b0dec1102 Mon Sep 17 00:00:00 2001 From: JanefrancessC Date: Wed, 1 Jul 2026 00:50:09 +0100 Subject: [PATCH 2/2] refactor: reuse remove() in pop_tail to avoid duplication --- Sprint-2/implement_linked_list/linked_list.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 8375940..516ba0d 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -1,12 +1,13 @@ class Node: """ - A node in a double linked list. + A node in a doubly linked list. Each node supports a data, previous, and next - data: the value - previous: pointer to the previous node - next: pointer to the next node """ + _slots_ = ("data", "previous", "next") def __init__(self, data): self.data = data @@ -69,19 +70,10 @@ def pop_tail(self): raise ValueError("List is empty.") # store value before removing node - value = self.tail.data + node = self.tail + value = node.data - if self.head == self.tail: - # Only one element in the list - self.head = None - self.tail = None - - else: - # Move tail pointer backwards - self.tail = self.tail.previous - - # Disconnect old tail node - self.tail.next = None + self.remove(node) return value