diff --git a/data_structures/linked_list/circular_linked_list.py b/data_structures/linked_list/circular_linked_list.py index d9544f426..72212f46b 100644 --- a/data_structures/linked_list/circular_linked_list.py +++ b/data_structures/linked_list/circular_linked_list.py @@ -6,16 +6,29 @@ from typing import Any class Node: def __init__(self, data: Any): + """ + Initialize a new Node with the given data. + Args: + data: The data to be stored in the node. + """ self.data: Any = data - self.next: Node | None = None + self.next: Node | None = None # Reference to the next node class CircularLinkedList: - def __init__(self): - self.head = None - self.tail = None + def __init__(self) -> None: + """ + Initialize an empty Circular Linked List. + """ + self.head = None # Reference to the head (first node) + self.tail = 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 self.head: yield node.data @@ -24,25 +37,48 @@ class CircularLinkedList: 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): + 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(data) if self.head is None: - new_node.next = new_node # first node points itself + new_node.next = new_node # First node points to itself self.tail = self.head = new_node - elif index == 0: # insert at head + elif index == 0: # Insert at the head new_node.next = self.head self.head = self.tail.next = new_node else: @@ -51,22 +87,43 @@ class CircularLinkedList: temp = temp.next new_node.next = temp.next temp.next = new_node - if index == len(self) - 1: # insert at tail + if index == len(self) - 1: # Insert at the tail self.tail = new_node - def delete_front(self): + 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.") delete_node = self.head - if self.head == self.tail: # just one node + if self.head == self.tail: # Just one node self.head = self.tail = None - elif index == 0: # delete head node + elif index == 0: # Delete head node self.tail.next = self.tail.next.next self.head = self.head.next else: @@ -75,16 +132,22 @@ class CircularLinkedList: temp = temp.next delete_node = temp.next temp.next = temp.next.next - if index == len(self) - 1: # delete at tail + if index == len(self) - 1: # Delete at 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() diff --git a/data_structures/linked_list/swap_nodes.py b/data_structures/linked_list/swap_nodes.py index 3f825756b..da6aa07a7 100644 --- a/data_structures/linked_list/swap_nodes.py +++ b/data_structures/linked_list/swap_nodes.py @@ -2,30 +2,56 @@ from typing import Any class Node: - def __init__(self, data: Any): + def __init__(self, data: Any) -> None: + """ + Initialize a new Node with the given data. + + Args: + data: The data to be stored in the node. + + """ self.data = data - self.next = None + self.next = None # Reference to the next node class LinkedList: - def __init__(self): - self.head = None + def __init__(self) -> None: + """ + Initialize an empty Linked List. + """ + self.head = None # Reference to the head (first node) def print_list(self): + """ + Print the elements of the Linked List in order. + """ temp = self.head while temp is not None: print(temp.data, end=" ") temp = temp.next print() - # adding nodes - def push(self, new_data: Any): + def push(self, new_data: Any) -> None: + """ + Add a new node with the given data to the beginning of the Linked List. + Args: + new_data (Any): The data to be added to the new node. + """ new_node = Node(new_data) new_node.next = self.head self.head = new_node - # swapping nodes - def swap_nodes(self, node_data_1, node_data_2): + def swap_nodes(self, node_data_1, node_data_2) -> None: + """ + Swap the positions of two nodes in the Linked List based on their data values. + Args: + node_data_1: Data value of the first node to be swapped. + node_data_2: Data value of the second node to be swapped. + + + Note: + If either of the specified data values isn't found then, no swapping occurs. + """ if node_data_1 == node_data_2: return else: @@ -40,6 +66,7 @@ class LinkedList: if node_1 is None or node_2 is None: return + # Swap the data values of the two nodes node_1.data, node_2.data = node_2.data, node_1.data @@ -48,8 +75,10 @@ if __name__ == "__main__": for i in range(5, 0, -1): ll.push(i) + print("Original Linked List:") ll.print_list() ll.swap_nodes(1, 4) - print("After swapping") + print("After swapping the nodes whose data is 1 and 4:") + ll.print_list()