doubly linked list: add dataclass and typing (#12647)

* Node is a dataclass

* fix mypy errors

* LinkedList is a dataclass

* fix mypy errors

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

* Update doubly_linked_list_two.py

---------

Co-authored-by: Maxim Smolskiy <mithridatus@mail.ru>
This commit is contained in:
Isidro 2025-04-01 20:55:14 +02:00 committed by GitHub
parent f10a5cbfcc
commit baab802965
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -9,25 +9,19 @@
Delete operation is more efficient Delete operation is more efficient
""" """
from dataclasses import dataclass
from typing import Self
@dataclass
class Node: class Node:
def __init__(self, data: int, previous=None, next_node=None): data: int
self.data = data previous: Self | None = None
self.previous = previous next: Self | None = None
self.next = next_node
def __str__(self) -> str: def __str__(self) -> str:
return f"{self.data}" return f"{self.data}"
def get_data(self) -> int:
return self.data
def get_next(self):
return self.next
def get_previous(self):
return self.previous
class LinkedListIterator: class LinkedListIterator:
def __init__(self, head): def __init__(self, head):
@ -40,30 +34,30 @@ class LinkedListIterator:
if not self.current: if not self.current:
raise StopIteration raise StopIteration
else: else:
value = self.current.get_data() value = self.current.data
self.current = self.current.get_next() self.current = self.current.next
return value return value
@dataclass
class LinkedList: class LinkedList:
def __init__(self): head: Node | None = None # First node in list
self.head = None # First node in list tail: Node | None = None # Last node in list
self.tail = None # Last node in list
def __str__(self): def __str__(self):
current = self.head current = self.head
nodes = [] nodes = []
while current is not None: while current is not None:
nodes.append(current.get_data()) nodes.append(current.data)
current = current.get_next() current = current.next
return " ".join(str(node) for node in nodes) return " ".join(str(node) for node in nodes)
def __contains__(self, value: int): def __contains__(self, value: int):
current = self.head current = self.head
while current: while current:
if current.get_data() == value: if current.data == value:
return True return True
current = current.get_next() current = current.next
return False return False
def __iter__(self): def __iter__(self):
@ -71,12 +65,12 @@ class LinkedList:
def get_head_data(self): def get_head_data(self):
if self.head: if self.head:
return self.head.get_data() return self.head.data
return None return None
def get_tail_data(self): def get_tail_data(self):
if self.tail: if self.tail:
return self.tail.get_data() return self.tail.data
return None return None
def set_head(self, node: Node) -> None: def set_head(self, node: Node) -> None:
@ -103,18 +97,20 @@ class LinkedList:
node_to_insert.next = node node_to_insert.next = node
node_to_insert.previous = node.previous node_to_insert.previous = node.previous
if node.get_previous() is None: if node.previous is None:
self.head = node_to_insert self.head = node_to_insert
else: else:
node.previous.next = node_to_insert node.previous.next = node_to_insert
node.previous = node_to_insert node.previous = node_to_insert
def insert_after_node(self, node: Node, node_to_insert: Node) -> None: def insert_after_node(self, node: Node | None, node_to_insert: Node) -> None:
assert node is not None
node_to_insert.previous = node node_to_insert.previous = node
node_to_insert.next = node.next node_to_insert.next = node.next
if node.get_next() is None: if node.next is None:
self.tail = node_to_insert self.tail = node_to_insert
else: else:
node.next.previous = node_to_insert node.next.previous = node_to_insert
@ -136,27 +132,27 @@ class LinkedList:
def get_node(self, item: int) -> Node: def get_node(self, item: int) -> Node:
node = self.head node = self.head
while node: while node:
if node.get_data() == item: if node.data == item:
return node return node
node = node.get_next() node = node.next
raise Exception("Node not found") raise Exception("Node not found")
def delete_value(self, value): def delete_value(self, value):
if (node := self.get_node(value)) is not None: if (node := self.get_node(value)) is not None:
if node == self.head: if node == self.head:
self.head = self.head.get_next() self.head = self.head.next
if node == self.tail: if node == self.tail:
self.tail = self.tail.get_previous() self.tail = self.tail.previous
self.remove_node_pointers(node) self.remove_node_pointers(node)
@staticmethod @staticmethod
def remove_node_pointers(node: Node) -> None: def remove_node_pointers(node: Node) -> None:
if node.get_next(): if node.next:
node.next.previous = node.previous node.next.previous = node.previous
if node.get_previous(): if node.previous:
node.previous.next = node.next node.previous.next = node.next
node.next = None node.next = None