Skip to content

Added SkipList #1781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 5, 2020
Merged
Changes from 1 commit
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
63 changes: 45 additions & 18 deletions data_structures/linked_list/skip_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,56 @@
https://epaperpress.com/sortsearch/download/skiplist.pdf
"""

from typing import List, Tuple, Optional
from typing import List, Tuple, Optional, TypeVar, Generic
from random import random

KT = TypeVar("KT")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable naming can be improved here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming is same as in cpython standard library.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will from typing import KT work?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Python developers clearly does not want to export them.

VT = TypeVar("VT")


class Node(Generic[KT, VT]):
def __init__(self, key: KT, value: VT):
self.key = key
self.value = value
self.forward: List[Node[KT, VT]] = []

class Node:
def __repr__(self):
"""
:return: Visual representation of Node

>>> node = Node("Key", 2)
>>> repr(node)
'Node(Key: 2)'
"""

return f"Node({self.key}: {self.value})"

@property
def level(self) -> int:
"""
:return: Number of forward references

>>> node = Node("Key", 2)
>>> node.level
0
>>> node.forward.append(Node("Key2", 4))
>>> node.level
1
>>> node.forward.append(Node("Key3", 6))
>>> node.level
2
"""

return len(self.forward)

def __init__(self, key, value):
self.key = key
self.value = value
self.forward: List[Node] = []

class SkipList(Generic[KT, VT]):
def __init__(self, p: float = 0.5, max_level: int = 16):
self.head: Node = Node("root", None)
self.level: int = 0
self.p = p
self.max_level = max_level

class SkipList:
def __str__(self):
items = list(self)

Expand Down Expand Up @@ -66,7 +97,7 @@ def random_level(self) -> int:

return level

def _locate_node(self, key) -> Tuple[Optional[Node], List[Node]]:
def _locate_node(self, key) -> Tuple[Optional[Node[KT, VT]], List[Node[KT, VT]]]:
"""
:param key: Searched key,
:return: Tuple with searched node (or None if given key is not present)
Expand All @@ -76,7 +107,7 @@ def _locate_node(self, key) -> Tuple[Optional[Node], List[Node]]:
# Nodes with refer or should refer to output node
update_vector = []

node: Node = self.head
node = self.head

for i in reversed(range(self.level)):
# i < node.level - When node level is lesser than `i` decrement `i`.
Expand All @@ -99,7 +130,7 @@ def _locate_node(self, key) -> Tuple[Optional[Node], List[Node]]:
else:
return None, update_vector

def delete(self, key):
def delete(self, key: KT):
"""
:param key: Key to remove from list.

Expand All @@ -109,7 +140,7 @@ def delete(self, key):
>>> skip_list.insert(3, "Three")
>>> list(skip_list)
[1, 2, 3]
>>> skip_list.delete(2,)
>>> skip_list.delete(2)
>>> list(skip_list)
[1, 3]
"""
Expand All @@ -125,7 +156,7 @@ def delete(self, key):
else:
update_node.forward = update_node.forward[:i]

def insert(self, key, value):
def insert(self, key: KT, value: VT):
"""
:param key: Key to insert.
:param value: Value associated with given key.
Expand Down Expand Up @@ -162,7 +193,7 @@ def insert(self, key, value):
else:
update_node.forward[i] = new_node

def find(self, key):
def find(self, key: VT) -> Optional[VT]:
"""
:param key: Search key.
:return: Value associated with given key or None if given key is not present.
Expand All @@ -182,11 +213,7 @@ def find(self, key):
if node is not None:
return node.value

def __init__(self, p: float = 0.5, max_level: int = 16):
self.head = Node("root", None)
self.level = 0
self.p = p
self.max_level = max_level
return None


def test_insert():
Expand Down