Skip to content

Instantly share code, notes, and snippets.

@hspedro
Last active December 5, 2021 19:43
Show Gist options
  • Save hspedro/253afbda49f383f4e7b17e9ae73ab63a to your computer and use it in GitHub Desktop.
Save hspedro/253afbda49f383f4e7b17e9ae73ab63a to your computer and use it in GitHub Desktop.
Custom Singly-Linked List in Python
from __future__ import annotations
from typing import Any, List, Optional
class SLLNode:
def __init__(self, data: Any, next_node: Optional[SLLNode] = None):
self.data = data
self.next_node = next_node
def __str__(self):
return f"{self.data}"
class SinglyLinkedList:
""" Custom implementation of a Singly-Linked List"""
def __init__(self, nodes: Optional[List[SLLNode]] = None):
# Note: the HEAD node will only contain data as 'HEAD' to
# print the list. See: __repr__()
self.HEAD = SLLNode('HEAD', next_node=None)
if nodes is not None:
for node in nodes:
self.append(node.data)
def __iter__(self):
node = self.HEAD
while node is not None:
yield node
node = node.next_node
def __len__(self) -> int:
return len([node for node in self]) - 1
def __contains__(self, data: Any) -> bool:
for node in self:
if node.data == data:
return True
return False
def __str__(self) -> str:
node = self.HEAD
nodes = []
for node in self:
nodes.append(str(node))
nodes.append('None')
return ' -> '.join(nodes)
def __getitem__(self, index: int) -> SLLNode:
if index < 0 and index > len(self) - 1:
raise IndexError(f'Index {index} out of range')
node = self.HEAD
for _ in range(index):
node = node.next_node
return node.next_node
def __setitem__(self, index: int, data: Any) -> SinglyLinkedList:
if index < 0 and index > len(self) - 1:
raise IndexError(f'Index {index} out of range')
node = self.HEAD
for _ in range(index + 1):
node = node.next_node
node.data = data
return self
def __delitem__(self, index: int):
if index < 0 and index > len(self) - 1:
raise IndexError(f'Index {index} out of range')
node = self.HEAD
for _ in range(index):
node = node.next_node
node.next_node = node.next_node.next_node if node.next_node else None
return
def __gt__(self, other: SinglyLinkedList) -> bool:
if len(self) > len(other):
return True
def __lt__(self, other: SinglyLinkedList) -> bool:
if len(self) < len(other):
return True
def __ge__(self, other: SinglyLinkedList) -> bool:
if len(self) >= len(other):
return True
def __le__(self, other: SinglyLinkedList) -> bool:
if len(self) <= len(other):
return True
def __eq__(self, other: SinglyLinkedList) -> bool:
if len(self) != len(other):
return False
for node in self:
if node.data != other[node.data]:
return False
return True
def __ne__(self, other: SinglyLinkedList) -> bool:
return not self == other
def append(self, data: Any) -> SinglyLinkedList:
node = self.HEAD
for node in self:
pass
node.next_node = SLLNode(data)
return self
def pop(self) -> Optional[SLLNode]:
if self.HEAD.next_node is None:
return None
node = self.HEAD
while node.next_node.next_node:
node = node.next_node
removed_node = node.next_node
node.next_node = None
return removed_node
def appendleft(self, data: Any) -> SinglyLinkedList:
new_node = SLLNode(data)
if self.HEAD.next_node is None:
self.HEAD.next_node = SLLNode(data)
return self
previous_first = self.HEAD.next_node
self.HEAD.next_node = new_node
new_node.next_node = previous_first
return self
def popleft(self) -> SLLNode:
if self.HEAD.next_node is None:
return None
previous_first = self.HEAD.next_node
self.HEAD.next_node = previous_first.next_node
return previous_first
def find(self, data: Any) -> Optional[SLLNode]:
if self.HEAD.next_node is None:
return None
for node in self:
if node.data == data:
return node
def remove(self, data: Any) -> SinglyLinkedList:
if self.HEAD.next_node is None:
return None
for node in self:
if node.next_node.data == data:
node.next_node = node.next_node.next_node
return self
if __name__ == '__main__':
ll = SinglyLinkedList([1, 2, 3])
print(f'SinglyLinkedList __init__: {ll}')
print(f'SinglyLinkedList __len__: {len(ll)}')
ll.append('abc')
print(f'appendleft: "abc" {ll}')
removed = ll.pop()
print(f'pop: removed = {removed}, {ll}')
ll.appendleft('xyz')
print(f'appendleft: "xyz" {ll}')
removed = ll.popleft()
print(f'popleft: removed = {removed}, {ll}')
print(f'__getitem__: @[1]: {ll[1]}')
ll[2] = 'foobar'
print(f'__setitem__: {ll}')
del ll[1]
print(f'__delitem__: @[1]: {ll}')
print(f'__contains__: "foobar": {("foobar" in ll)}')
print(f'__gt__: {(ll > SinglyLinkedList([1, 2, 3, 4, 5]))}')
print(f'__ge__: {(ll >= SinglyLinkedList(range(len(ll))))}')
print(f'__lt__: {(ll < SinglyLinkedList([1]))}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment