Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions Sprint-2/implement_linked_list/linked_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

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

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
11 changes: 11 additions & 0 deletions Sprint-2/implement_linked_list/linked_list_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__":
Expand Down
87 changes: 87 additions & 0 deletions Sprint-2/implement_skip_list/skip_list.py
Original file line number Diff line number Diff line change
@@ -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
28 changes: 27 additions & 1 deletion Sprint-2/implement_skip_list/skip_list_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()