Skip to content

devdatta #11546

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

Closed
wants to merge 3 commits into from
Closed

devdatta #11546

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
102 changes: 20 additions & 82 deletions data_structures/linked_list/circular_linked_list.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from __future__ import annotations

from collections.abc import Iterator
from dataclasses import dataclass
from typing import Any


@dataclass

Check failure on line 7 in data_structures/linked_list/circular_linked_list.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (I001)

data_structures/linked_list/circular_linked_list.py:1:1: I001 Import block is un-sorted or un-formatted
class Node:
data: Any
next_node: Node | None = None
Expand All @@ -17,142 +16,81 @@
tail: Node | None = None # Reference to the tail (last node)

def __iter__(self) -> Iterator[Any]:
"""
Iterate through all nodes in the Circular Linked List yielding their data.
Yields:
The data of each node in the linked list.
"""
node = self.head
while node:
if node is None:
return
while True:
yield node.data
node = node.next_node
if node == self.head:
break

def __len__(self) -> int:
"""
Get the length (number of nodes) in the Circular Linked List.
"""
return sum(1 for _ in self)

def __repr__(self) -> str:
"""
Generate a string representation of the Circular Linked List.
Returns:
A string of the format "1->2->....->N".
"""
return "->".join(str(item) for item in iter(self))

def insert_tail(self, data: Any) -> None:
"""
Insert a node with the given data at the end of the Circular Linked List.
"""
self.insert_nth(len(self), data)

def insert_head(self, data: Any) -> None:
"""
Insert a node with the given data at the beginning of the Circular Linked List.
"""
self.insert_nth(0, data)

def insert_nth(self, index: int, data: Any) -> None:
"""
Insert the data of the node at the nth pos in the Circular Linked List.
Args:
index: The index at which the data should be inserted.
data: The data to be inserted.

Raises:
IndexError: If the index is out of range.
"""
if index < 0 or index > len(self):
raise IndexError("list index out of range.")
new_node: Node = Node(data)
new_node = Node(data)
if self.head is None:
new_node.next_node = new_node # First node points to itself
self.tail = self.head = new_node
elif index == 0: # Insert at the head
# List is empty, so new node is both head and tail, pointing to itself
new_node.next_node = new_node
self.head = self.tail = new_node
elif index == 0: # Insert at head
new_node.next_node = self.head
assert self.tail is not None # List is not empty, tail exists
self.head = self.tail.next_node = new_node
self.tail.next_node = new_node
self.head = new_node
else:
temp: Node | None = self.head
temp = self.head
for _ in range(index - 1):
assert temp is not None
temp = temp.next_node
assert temp is not None
new_node.next_node = temp.next_node
temp.next_node = new_node
if index == len(self) - 1: # Insert at the tail
if temp == self.tail: # Insert at the tail
self.tail = new_node

def delete_front(self) -> Any:
"""
Delete and return the data of the node at the front of the Circular Linked List.
Raises:
IndexError: If the list is empty.
"""
return self.delete_nth(0)

def delete_tail(self) -> Any:
"""
Delete and return the data of the node at the end of the Circular Linked List.
Returns:
Any: The data of the deleted node.
Raises:
IndexError: If the index is out of range.
"""
return self.delete_nth(len(self) - 1)

def delete_nth(self, index: int = 0) -> Any:
"""
Delete and return the data of the node at the nth pos in Circular Linked List.
Args:
index (int): The index of the node to be deleted. Defaults to 0.
Returns:
Any: The data of the deleted node.
Raises:
IndexError: If the index is out of range.
"""
if not 0 <= index < len(self):
raise IndexError("list index out of range.")
if self.head is None:
raise IndexError("Cannot delete from an empty list.")

assert self.head is not None
assert self.tail is not None
delete_node: Node = self.head
if self.head == self.tail: # Just one node
delete_node = self.head
if self.head == self.tail: # Only one node in the list
self.head = self.tail = None
elif index == 0: # Delete head node
assert self.tail.next_node is not None
self.tail.next_node = self.tail.next_node.next_node
self.tail.next_node = self.head.next_node
self.head = self.head.next_node
else:
temp: Node | None = self.head
temp = self.head
for _ in range(index - 1):
assert temp is not None
temp = temp.next_node
assert temp is not None
assert temp.next_node is not None
delete_node = temp.next_node
temp.next_node = temp.next_node.next_node
if index == len(self) - 1: # Delete at tail
temp.next_node = delete_node.next_node
if delete_node == self.tail: # If deleting the tail
self.tail = temp
return delete_node.data

def is_empty(self) -> bool:
"""
Check if the Circular Linked List is empty.
Returns:
bool: True if the list is empty, False otherwise.
"""
return len(self) == 0


def test_circular_linked_list() -> None:
"""
Test cases for the CircularLinkedList class.
>>> test_circular_linked_list()
"""
circular_linked_list = CircularLinkedList()
assert len(circular_linked_list) == 0
assert circular_linked_list.is_empty() is True
Expand Down
Loading