From e862c3bdfc375038301bbc115ca7e652a73c01c2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 27 Feb 2026 00:26:01 +0000 Subject: [PATCH 1/7] copying my linked list implementation into this new branch as I mistakenly commited into main and thus my PR failed. --- Sprint-2/implement_linked_list/linked_list.py | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index e69de29..84a354a 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -0,0 +1,64 @@ +class Node: + def __init__(self, data): + self.data = data + self.previous = None + self.next = None + +class LinkedList: + def __init__(self): + self.head = None + self.tail = None + + def push_head(self, data): + new_head_node = Node(data) + if self.head is not None: + new_head_node.next = self.head + self.head.previous = new_head_node + + self.head = new_head_node + if self.tail is None: + self.tail = new_head_node + + return new_head_node + + + + def pop_tail(self): + if self.tail is not None: + tail_node = self.tail + previous = self.tail.previous + self.tail = previous + if self.tail is not None: + self.tail.next = None + else: + self.head = None + else: + raise IndexError("Unable to remove from empty linked list") + + return tail_node.data + + + + def remove(self, node): + if node.previous is not None: + node.previous.next = node.next + else: + self.head = node.next + + if node.next is not None: + node.next.previous = node.previous + else: + self.tail = node.previous + + + + + + + + + + + + + From dc94ae0eebb00f19df44da6fcc07faabda62c46b Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 27 Feb 2026 15:09:14 +0000 Subject: [PATCH 2/7] update the linked_list_test --- Sprint-2/implement_linked_list/linked_list_test.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list_test.py b/Sprint-2/implement_linked_list/linked_list_test.py index d59d9c5..bf9aabc 100644 --- a/Sprint-2/implement_linked_list/linked_list_test.py +++ b/Sprint-2/implement_linked_list/linked_list_test.py @@ -34,6 +34,20 @@ def test_remove_tail(self): self.assertIsNone(b.next) self.assertIsNone(b.previous) + def test_remove_middle(self): + l = LinkedList() + l.push_head("a") + b = l.push_head("b") + l.push_head("c") + + l.remove(b) + + self.assertIsNone(b.next) + self.assertIsNone(b.previous) + + self.assertEqual(l.pop_tail(), "a") + self.assertEqual(l.pop_tail(), "c") + if __name__ == "__main__": unittest.main() From 5100b369435fa023c7ed06c5eea1ce54dd49ace8 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 27 Feb 2026 17:06:51 +0000 Subject: [PATCH 3/7] update the pop_tail method to first handle when ta linked list is empty and thus throw error to eliminate having to deal with special cases after this point --- Sprint-2/implement_linked_list/linked_list.py | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 84a354a..bfb528f 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -24,18 +24,20 @@ def push_head(self, data): def pop_tail(self): - if self.tail is not None: - tail_node = self.tail - previous = self.tail.previous - self.tail = previous - if self.tail is not None: - self.tail.next = None - else: - self.head = None - else: + if self.tail is None: raise IndexError("Unable to remove from empty linked list") + + # tail_node = self.tail + # previous = self.tail.previous + # self.tail = previous + # if self.tail is not None: + # self.tail.next = None + # else: + # self.head = None + # else: + - return tail_node.data + # return tail_node.data From addda43b815c80337c3f96893eefd62d7187cb63 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 27 Feb 2026 17:11:11 +0000 Subject: [PATCH 4/7] inside pop_tail method -once errors and speical cases are handled first, reposition the rest of the code at the end --- Sprint-2/implement_linked_list/linked_list.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index bfb528f..eb6de6c 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -27,17 +27,15 @@ def pop_tail(self): if self.tail is None: raise IndexError("Unable to remove from empty linked list") - # tail_node = self.tail - # previous = self.tail.previous - # self.tail = previous - # if self.tail is not None: - # self.tail.next = None - # else: - # self.head = None - # else: - + tail_node = self.tail + previous = self.tail.previous + self.tail = previous + if self.tail is not None: + self.tail.next = None + else: + self.head = None - # return tail_node.data + return tail_node.data From 301d10d1b5c1d40e7f9430f4fa3974482e452da0 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 27 Feb 2026 17:21:00 +0000 Subject: [PATCH 5/7] Once a node is removed ensure that it's prev and next points to none to ensure that it's fully isolated/disconnected --- Sprint-2/implement_linked_list/linked_list.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index eb6de6c..c46cddd 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -50,6 +50,9 @@ def remove(self, node): else: self.tail = node.previous + node.previous = None + node.next = None + From 56786ffacd048b62f711e1092ac92688cb902178 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 27 Feb 2026 20:47:52 +0000 Subject: [PATCH 6/7] updating remove method so that it first caputures neighboring nodes before removal/relinking to avoid possible bugs --- Sprint-2/implement_linked_list/linked_list.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index c46cddd..d5a66b2 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -40,15 +40,18 @@ def pop_tail(self): def remove(self, node): + previous_node = node.previous + next_node = node.next + if node.previous is not None: - node.previous.next = node.next + previous_node.next = next_node else: - self.head = node.next + self.head = next_node if node.next is not None: - node.next.previous = node.previous + next_node.previous = previous_node else: - self.tail = node.previous + self.tail = previous_node node.previous = None node.next = None From 7a292df34082a7ce68a37920c166ea57067770d3 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Sat, 28 Feb 2026 21:38:17 +0000 Subject: [PATCH 7/7] update pop_tail function so that the removed node's prev and next are pointing to None. This is to ensure the removed node is fully isolated and dromant. --- Sprint-2/implement_linked_list/linked_list.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index d5a66b2..774d38f 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -29,11 +29,15 @@ def pop_tail(self): tail_node = self.tail previous = self.tail.previous + self.tail = previous if self.tail is not None: self.tail.next = None else: self.head = None + + tail_node.previous = None + tail_node.next = None return tail_node.data