From 5e178ad8c107cebe9ada5bf3ea9e6b142abdfb6a Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 16:31:53 +0000 Subject: [PATCH 01/22] create a Node class that stores the value of the data it contains and references to both previous and next nodes --- Sprint-2/implement_linked_list/linked_list.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index e69de29..4c1dd35 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -0,0 +1,5 @@ +class Node: + def __init__(self, data): + self.data = data + self.prev = None + self.next = None \ No newline at end of file From d699eeb32f122d805c017a314d97686debb479f2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 16:41:33 +0000 Subject: [PATCH 02/22] Create anthor class that models the linked list --- Sprint-2/implement_linked_list/linked_list.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 4c1dd35..b4d8f77 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -2,4 +2,9 @@ class Node: def __init__(self, data): self.data = data self.prev = None - self.next = None \ No newline at end of file + self.next = None + +class LinkedList: + def __init__(self): + self.head = None + self.tail = None \ No newline at end of file From 2886aeb66a07e8b0afe3e98928a85a8a7a161a07 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 16:46:34 +0000 Subject: [PATCH 03/22] define a function that push a new node to the beginning of the linked list + create a node object to represents that node that will become the new head --- Sprint-2/implement_linked_list/linked_list.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index b4d8f77..4d8acd4 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -7,4 +7,7 @@ def __init__(self, data): class LinkedList: def __init__(self): self.head = None - self.tail = None \ No newline at end of file + self.tail = None + + def push_head(self, data): + new_head_node = Node(data) \ No newline at end of file From 1e691d71a20fc36c8d3a0f8072c0eab2ce1e5d2a Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 16:51:52 +0000 Subject: [PATCH 04/22] check if the linked list have nodes, if so, appoints the new object to become head of the linked list. --- Sprint-2/implement_linked_list/linked_list.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 4d8acd4..4f237e7 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -10,4 +10,6 @@ def __init__(self): self.tail = None def push_head(self, data): - new_head_node = Node(data) \ No newline at end of file + new_head_node = Node(data) + if self.head is not None: + new_head_node.next = self.head From 1ccff69a173a5f185285b691a2f98c48828ffebb Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 16:55:48 +0000 Subject: [PATCH 05/22] update the "former" head node's prev pointer to point to the new head ndoe --- Sprint-2/implement_linked_list/linked_list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 4f237e7..f09dd97 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -13,3 +13,4 @@ def push_head(self, data): new_head_node = Node(data) if self.head is not None: new_head_node.next = self.head + self.head.prev = new_head_node From 361c2e3a7712870c8cf55e156db46a12eda3b8b2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 16:57:07 +0000 Subject: [PATCH 06/22] make the new created node as the head node incase that the linked list is empty --- Sprint-2/implement_linked_list/linked_list.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index f09dd97..82e7655 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -14,3 +14,5 @@ def push_head(self, data): if self.head is not None: new_head_node.next = self.head self.head.prev = new_head_node + + self.head = new_head_node From 609ccd1842c5714a96057bf02922b47479346624 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 19:08:22 +0000 Subject: [PATCH 07/22] update logic so that it check if the linked list is empty if so to the new created ndoes becomes the tail node too --- 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 82e7655..4798168 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -16,3 +16,7 @@ def push_head(self, data): self.head.prev = new_head_node self.head = new_head_node + if self.tail is None: + self.tail = new_head_node + + return new_head_node From f7ef01ca68a568107c8fc4471351f9cae12df7fc Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 20:02:14 +0000 Subject: [PATCH 08/22] create pop_tail function that checks if the linked list has nodes in it, if so, disconnect the tail so it gets removed. --- Sprint-2/implement_linked_list/linked_list.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 4798168..72b1d5f 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -20,3 +20,10 @@ def push_head(self, data): self.tail = new_head_node return new_head_node + + + + def pop_tail(self): + if self.tail is not None: + self.tail.next = None + From 8daafebce1d95d19cce0d5c650f90d43cfe37589 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 20:20:17 +0000 Subject: [PATCH 09/22] when linekd array has nodes, udpate pointers to get rid of the tail. --- 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 72b1d5f..af7af6d 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -25,5 +25,9 @@ def push_head(self, data): def pop_tail(self): if self.tail is not None: + tail_node = self.tail + node = self.tail.prev + self.tail = node self.tail.next = None + self.tail.prev != None From 6abcd50374ac12356eed4191be25c021757a4191 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 20:26:11 +0000 Subject: [PATCH 10/22] move the pointer to tail node to point the the previous node --- Sprint-2/implement_linked_list/linked_list.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index af7af6d..511ebe1 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -28,6 +28,6 @@ def pop_tail(self): tail_node = self.tail node = self.tail.prev self.tail = node - self.tail.next = None - self.tail.prev != None + + From 4518f34c002a2ef44fc0ba8620b04c6044806e69 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 20:29:56 +0000 Subject: [PATCH 11/22] after repositioning pointer of last node towards the seond to last node., disconnect from the node that comes after it (initial tail node) --- Sprint-2/implement_linked_list/linked_list.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 511ebe1..5016b52 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -28,6 +28,8 @@ def pop_tail(self): tail_node = self.tail node = self.tail.prev self.tail = node + node.next = None + From 8718bde5c08e4c0898fa7a5a2012be32d0907e11 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 20:34:20 +0000 Subject: [PATCH 12/22] add if condition so that logic handles when linked list has more than one node in it. --- Sprint-2/implement_linked_list/linked_list.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 5016b52..e1ae486 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -28,7 +28,9 @@ def pop_tail(self): tail_node = self.tail node = self.tail.prev self.tail = node - node.next = None + if self.tail is not None: + self.tail.next = None + From 6bce59e76de50d7a1544df4bb8f371ff7649c684 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 20:40:27 +0000 Subject: [PATCH 13/22] update logic to handle when linked list is empty: Throw an error --- 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 e1ae486..be8fc61 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -30,6 +30,9 @@ def pop_tail(self): self.tail = node if self.tail is not None: self.tail.next = None + else: + raise IndexError("Unable to remove from empty linked list") + From 97552b40e41a45275371b71772d7a43f31711c36 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 20:49:48 +0000 Subject: [PATCH 14/22] add a return to pop_tail to pass tests --- Sprint-2/implement_linked_list/linked_list.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index be8fc61..875acc3 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -14,7 +14,7 @@ def push_head(self, data): if self.head is not None: new_head_node.next = self.head self.head.prev = new_head_node - + self.head = new_head_node if self.tail is None: self.tail = new_head_node @@ -32,6 +32,8 @@ def pop_tail(self): self.tail.next = None else: raise IndexError("Unable to remove from empty linked list") + + return tail_node.data From 1a94c7e648d48d8af0a50b4da2180d419ea6f232 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 22:26:25 +0000 Subject: [PATCH 15/22] update pop_tail function to handle when there's one node in the linked list --- Sprint-2/implement_linked_list/linked_list.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 875acc3..f4389ce 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -30,6 +30,8 @@ def pop_tail(self): self.tail = node if self.tail is not None: self.tail.next = None + else: + self.head = None else: raise IndexError("Unable to remove from empty linked list") From 5664fdd984b873ef058bd50bce76609608d226d1 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 22:35:13 +0000 Subject: [PATCH 16/22] since test require "previous", replacing all mentions to "prev" with "previous" so that tests pass --- Sprint-2/implement_linked_list/linked_list.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index f4389ce..a4506ad 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -1,7 +1,7 @@ class Node: def __init__(self, data): self.data = data - self.prev = None + self.previous = None self.next = None class LinkedList: @@ -13,7 +13,7 @@ def push_head(self, data): new_head_node = Node(data) if self.head is not None: new_head_node.next = self.head - self.head.prev = new_head_node + self.head.previous = new_head_node self.head = new_head_node if self.tail is None: @@ -26,8 +26,8 @@ def push_head(self, data): def pop_tail(self): if self.tail is not None: tail_node = self.tail - node = self.tail.prev - self.tail = node + previous = self.tail.previous + self.tail = previous if self.tail is not None: self.tail.next = None else: From b68f8032ed5186dda8b12456bf5025a9d037d1ee Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 22:59:41 +0000 Subject: [PATCH 17/22] build remove function - make it check if there's a node before our current node - if so reposition pointer so it's disconnected from the linked list --- Sprint-2/implement_linked_list/linked_list.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index a4506ad..40d5b0e 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -36,6 +36,18 @@ def pop_tail(self): 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 + + + + + + From 3139f6d5b23b8eb15fa5565b313e9de4e920ab38 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 23:05:24 +0000 Subject: [PATCH 18/22] update logic inside remove function so that when the current node is the head, the next node becomes the new head and thus current node disconnected and removed from linked list. --- Sprint-2/implement_linked_list/linked_list.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 40d5b0e..ab4e759 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -42,6 +42,8 @@ def pop_tail(self): def remove(self, node): if node.previous is not None: node.previous.next = node.next + else: + self.head = node.next From aec744166fd938f988be17fd10d1bf65909849f5 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 23:28:24 +0000 Subject: [PATCH 19/22] updat remove function to handle when node points to other next node in the linked list - if so reposition pointers so curent node is removed. else if the current node is the tail make the previous node to it the "new" tail --- Sprint-2/implement_linked_list/linked_list.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index ab4e759..84a354a 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -44,6 +44,12 @@ def remove(self, node): 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 a9ee5b0987a5175a167cf361748ff43ea3e09f19 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 23:31:20 +0000 Subject: [PATCH 20/22] ignore VM for Sprint 2 --- Sprint-2/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 Sprint-2/.gitignore diff --git a/Sprint-2/.gitignore b/Sprint-2/.gitignore new file mode 100644 index 0000000..0cafc1c --- /dev/null +++ b/Sprint-2/.gitignore @@ -0,0 +1 @@ +.venv/ \ No newline at end of file From f54da601db13f51a9452cf7928da55ddf7007276 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 26 Feb 2026 23:43:25 +0000 Subject: [PATCH 21/22] create a branch so that pull request can be pushed --- Sprint-2/implement_linked_list/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sprint-2/implement_linked_list/README.md b/Sprint-2/implement_linked_list/README.md index 50c44a8..e9d95ec 100644 --- a/Sprint-2/implement_linked_list/README.md +++ b/Sprint-2/implement_linked_list/README.md @@ -9,3 +9,5 @@ It should support the following operations. Each operation should have a O(1) wo * `remove` takes a handle from `push_head`, and removes that element from the list. There are some tests in `linked_list_test.py` for your implementation - feel free to write more. + +* A branch was later created so that a PR can be pushed. From ad51df9e7761d0074f5fc4a334528bf2d3ea0324 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 27 Feb 2026 00:18:34 +0000 Subject: [PATCH 22/22] update read me to explain a new branch created for this task so a pull request to can pushed --- Sprint-2/implement_linked_list/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sprint-2/implement_linked_list/README.md b/Sprint-2/implement_linked_list/README.md index e9d95ec..bec923c 100644 --- a/Sprint-2/implement_linked_list/README.md +++ b/Sprint-2/implement_linked_list/README.md @@ -11,3 +11,6 @@ It should support the following operations. Each operation should have a O(1) wo There are some tests in `linked_list_test.py` for your implementation - feel free to write more. * A branch was later created so that a PR can be pushed. + + +* Make a new branch for implementing linked list in python