From c81b61ad6f9e76fca2812e9622688682a6f663c2 Mon Sep 17 00:00:00 2001 From: DraftRoman Date: Wed, 10 Jun 2026 12:44:54 +0200 Subject: [PATCH 1/3] Node class (value: stored data | next: pointer to next node | previous: pointer to previous node) LinkedList class state(head = first element | tail = last element) push_head(value) - Insert a new node at the start of the list --- Sprint-2/implement_linked_list/linked_list.py | 21 +++++++++++++++++++ .../implement_linked_list/linked_list_test.py | 11 ++++++++++ 2 files changed, 32 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index e69de29b..26306c48 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -0,0 +1,21 @@ + +class LinkedList: + class Node: + def __init__(self, value): + self.value = value + self.next = None + self.previous = None + + def __init__(self): + self.head = None + self.tail = None + + def push_head(self, value): + node = LinkedList.Node(value) + if self.head is not None: + node.next = self.head + self.head.previous = node + else: + self.tail = node + self.head = node + return node diff --git a/Sprint-2/implement_linked_list/linked_list_test.py b/Sprint-2/implement_linked_list/linked_list_test.py index d59d9c5c..082f8446 100644 --- a/Sprint-2/implement_linked_list/linked_list_test.py +++ b/Sprint-2/implement_linked_list/linked_list_test.py @@ -33,6 +33,17 @@ def test_remove_tail(self): self.assertEqual(l.tail, b) self.assertIsNone(b.next) self.assertIsNone(b.previous) + + def test_remove_head(self): + l = LinkedList() + a = l.push_head("a") + b = l.push_head("b") + l.remove(b) + self.assertEqual(l.head, a) + self.assertEqual(l.tail, a) + self.assertIsNone(a.next) + self.assertIsNone(a.previous) + if __name__ == "__main__": From 014dc76cf96a038c962ba3b43fe712e0c75df66b Mon Sep 17 00:00:00 2001 From: DraftRoman Date: Wed, 10 Jun 2026 13:23:59 +0200 Subject: [PATCH 2/3] push_head(value) - Insert a new node at the start of the list | pop_tail() - Remove and return last element --- Sprint-2/implement_linked_list/linked_list.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 26306c48..fca785e9 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -19,3 +19,24 @@ def push_head(self, value): self.tail = node self.head = node return node + + def pop_tail(self): + if self.tail is None: + raise IndexError("pop from empty list") + value = self.tail.value + if self.tail.previous is not None: + self.tail.previous.next = None + else: + self.head = None + self.tail = self.tail.previous + return value + + 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 \ No newline at end of file From 9e511443fa954801cca71574f2aeb043f76d9c8d Mon Sep 17 00:00:00 2001 From: DraftRoman Date: Thu, 11 Jun 2026 18:28:09 +0200 Subject: [PATCH 3/3] skip_list.py and test test_duplicates | test_empty_skip_list | test_search_non_existent --- Sprint-2/implement_skip_list/skip_list.py | 87 +++++++++++++++++++ .../implement_skip_list/skip_list_test.py | 28 +++++- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 Sprint-2/implement_skip_list/skip_list.py diff --git a/Sprint-2/implement_skip_list/skip_list.py b/Sprint-2/implement_skip_list/skip_list.py new file mode 100644 index 00000000..897462f1 --- /dev/null +++ b/Sprint-2/implement_skip_list/skip_list.py @@ -0,0 +1,87 @@ +import random + + +class Node: + def __init__(self, value, level): + self.value = value + self.forward = [None] * level + + +class SkipList: + + MAX_LEVEL = 4 + + def __init__(self): + self.head = Node(-1, self.MAX_LEVEL) + self.level = 1 + + def random_level(self): + + level = 1 + + while random.random() < 0.5 and level < self.MAX_LEVEL: + level += 1 + + return level + + def search(self, value): + + current = self.head + + for i in range(self.level - 1, -1, -1): + + while ( + current.forward[i] + and current.forward[i].value < value + ): + current = current.forward[i] + + current = current.forward[0] + + return current is not None and current.value == value + + def insert(self, value): + + update = [None] * self.MAX_LEVEL + current = self.head + + for i in range(self.level - 1, -1, -1): + + while ( + current.forward[i] + and current.forward[i].value < value + ): + current = current.forward[i] + + update[i] = current + + new_level = self.random_level() + + if new_level > self.level: + + for i in range(self.level, new_level): + update[i] = self.head + + self.level = new_level + + new_node = Node(value, new_level) + + for i in range(new_level): + + new_node.forward[i] = update[i].forward[i] + update[i].forward[i] = new_node + + def __contains__(self, value): + return self.search(value) + + def to_list(self): + + result = [] + + current = self.head.forward[0] + + while current: + result.append(current.value) + current = current.forward[0] + + return result \ No newline at end of file diff --git a/Sprint-2/implement_skip_list/skip_list_test.py b/Sprint-2/implement_skip_list/skip_list_test.py index d20b102b..fae96776 100644 --- a/Sprint-2/implement_skip_list/skip_list_test.py +++ b/Sprint-2/implement_skip_list/skip_list_test.py @@ -25,7 +25,33 @@ def test_general_usage(self): self.assertNotIn(7, sl) self.assertEqual(sl.to_list(), [1, 2, 3, 4, 5, 10]) + + + def test_duplicates(self): + sl = SkipList() + sl.insert(1) + sl.insert(1) + sl.insert(1) + + self.assertEqual(sl.to_list(), [1, 1, 1]) + self.assertIn(1, sl) + self.assertNotIn(2, sl) + + def test_empty_skip_list(self): + sl = SkipList() + self.assertEqual(sl.to_list(), []) + self.assertNotIn(1, sl) + + def test_search_non_existent(self): + sl = SkipList() + sl.insert(1) + sl.insert(2) + sl.insert(3) + + self.assertNotIn(4, sl) + self.assertNotIn(0, sl) + if __name__ == "__main__": - unittest.main() + unittest.main() \ No newline at end of file