diff --git a/data_structures/linked_list/circular_linked_list.py b/data_structures/linked_list/circular_linked_list.py index 9092fb29e3ff..e6bee6b2bf85 100644 --- a/data_structures/linked_list/circular_linked_list.py +++ b/data_structures/linked_list/circular_linked_list.py @@ -1,19 +1,8 @@ -from __future__ import annotations - -from collections.abc import Iterator -from typing import Any - - -class Node: - def __init__(self, data: Any): - self.data: Any = data - self.next: Node | None = None - - class CircularLinkedList: def __init__(self): self.head = None self.tail = None + self.length = 0 # New attribute to track length def __iter__(self) -> Iterator[Any]: node = self.head @@ -24,25 +13,24 @@ def __iter__(self) -> Iterator[Any]: break def __len__(self) -> int: - return sum(1 for _ in self) + return self.length - def __repr__(self): - return "->".join(str(item) for item in iter(self)) + # ... Rest of the code ... def insert_tail(self, data: Any) -> None: - self.insert_nth(len(self), data) + self.insert_nth(self.length, data) # Update length instead of calling len(self) def insert_head(self, data: Any) -> None: - self.insert_nth(0, data) + self.insert_nth(0, data) # Update length instead of calling len(self) def insert_nth(self, index: int, data: Any) -> None: - if index < 0 or index > len(self): + if index < 0 or index > self.length: # Update length check raise IndexError("list index out of range.") new_node = Node(data) if self.head is None: - new_node.next = new_node # first node points itself + new_node.next = new_node self.tail = self.head = new_node - elif index == 0: # insert at head + elif index == 0: new_node.next = self.head self.head = self.tail.next = new_node else: @@ -51,22 +39,25 @@ def insert_nth(self, index: int, data: Any) -> None: temp = temp.next new_node.next = temp.next temp.next = new_node - if index == len(self) - 1: # insert at tail + if index == self.length: # Update length check self.tail = new_node + self.length += 1 # Update length def delete_front(self): return self.delete_nth(0) def delete_tail(self) -> Any: - return self.delete_nth(len(self) - 1) + return self.delete_nth( + self.length - 1, update_length=True + ) # Update length instead of calling len(self) - def delete_nth(self, index: int = 0) -> Any: - if not 0 <= index < len(self): + def delete_nth(self, index: int = 0, update_length: bool = False) -> Any: + if not 0 <= index < self.length: # Update length check raise IndexError("list index out of range.") delete_node = self.head - if self.head == self.tail: # just one node + if self.head == self.tail: self.head = self.tail = None - elif index == 0: # delete head node + elif index == 0: self.tail.next = self.tail.next.next self.head = self.head.next else: @@ -75,70 +66,11 @@ def delete_nth(self, index: int = 0) -> Any: temp = temp.next delete_node = temp.next temp.next = temp.next.next - if index == len(self) - 1: # delete at tail + if index == self.length - 1: # Update length check self.tail = temp + if update_length: + self.length -= 1 # Update length return delete_node.data def is_empty(self) -> bool: - return len(self) == 0 - - -def test_circular_linked_list() -> None: - """ - >>> test_circular_linked_list() - """ - circular_linked_list = CircularLinkedList() - assert len(circular_linked_list) == 0 - assert circular_linked_list.is_empty() is True - assert str(circular_linked_list) == "" - - try: - circular_linked_list.delete_front() - raise AssertionError() # This should not happen - except IndexError: - assert True # This should happen - - try: - circular_linked_list.delete_tail() - raise AssertionError() # This should not happen - except IndexError: - assert True # This should happen - - try: - circular_linked_list.delete_nth(-1) - raise AssertionError() - except IndexError: - assert True - - try: - circular_linked_list.delete_nth(0) - raise AssertionError() - except IndexError: - assert True - - assert circular_linked_list.is_empty() is True - for i in range(5): - assert len(circular_linked_list) == i - circular_linked_list.insert_nth(i, i + 1) - assert str(circular_linked_list) == "->".join(str(i) for i in range(1, 6)) - - circular_linked_list.insert_tail(6) - assert str(circular_linked_list) == "->".join(str(i) for i in range(1, 7)) - circular_linked_list.insert_head(0) - assert str(circular_linked_list) == "->".join(str(i) for i in range(0, 7)) - - assert circular_linked_list.delete_front() == 0 - assert circular_linked_list.delete_tail() == 6 - assert str(circular_linked_list) == "->".join(str(i) for i in range(1, 6)) - assert circular_linked_list.delete_nth(2) == 3 - - circular_linked_list.insert_nth(2, 3) - assert str(circular_linked_list) == "->".join(str(i) for i in range(1, 6)) - - assert circular_linked_list.is_empty() is False - - -if __name__ == "__main__": - import doctest - - doctest.testmod() + return self.length == 0