Skip to content
Closed
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
194 changes: 71 additions & 123 deletions data_structures/queues/linked_queue.py
Original file line number Diff line number Diff line change
@@ -1,156 +1,104 @@
"""A Queue using a linked list like structure"""
"""
Queue Implementation using Linked List (Optimized)

from __future__ import annotations
- Time Complexity:
enqueue → O(1)
dequeue → O(1)
is_empty → O(1)
size → O(1)

Author: Sufiyan
"""

from collections.abc import Iterator
from typing import Any
from __future__ import annotations
from typing import Any, Iterator

Check failure on line 14 in data_structures/queues/linked_queue.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (UP035)

data_structures/queues/linked_queue.py:14:1: UP035 Import from `collections.abc` instead: `Iterator` help: Import from `collections.abc`

Check failure on line 14 in data_structures/queues/linked_queue.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (I001)

data_structures/queues/linked_queue.py:13:1: I001 Import block is un-sorted or un-formatted help: Organize imports


class Node:
"""A node in the linked list."""

def __init__(self, data: Any) -> None:
self.data: Any = data
self.data = data
self.next: Node | None = None

def __str__(self) -> str:
return f"{self.data}"


class LinkedQueue:
"""
>>> queue = LinkedQueue()
>>> queue.is_empty()
True
>>> queue.put(5)
>>> queue.put(9)
>>> queue.put('python')
>>> queue.is_empty()
False
>>> queue.get()
5
>>> queue.put('algorithms')
>>> queue.get()
9
>>> queue.get()
'python'
>>> queue.get()
'algorithms'
>>> queue.is_empty()
True
>>> queue.get()
Traceback (most recent call last):
...
IndexError: dequeue from empty queue
"""
"""Efficient Queue implementation using a linked list (FIFO)."""

def __init__(self) -> None:
self.front: Node | None = None
self.rear: Node | None = None

def __iter__(self) -> Iterator[Any]:
node = self.front
while node:
yield node.data
node = node.next
self._size: int = 0 # 🔥 O(1) size tracking

def __len__(self) -> int:
"""
>>> queue = LinkedQueue()
>>> for i in range(1, 6):
... queue.put(i)
>>> len(queue)
5
>>> for i in range(1, 6):
... assert len(queue) == 6 - i
... _ = queue.get()
>>> len(queue)
0
"""
return len(tuple(iter(self)))
"""Return number of elements in queue (O(1))."""
return self._size

def __iter__(self) -> Iterator[Any]:
"""Iterate through elements."""
current = self.front
while current:
yield current.data
current = current.next

def __str__(self) -> str:
"""
>>> queue = LinkedQueue()
>>> for i in range(1, 4):
... queue.put(i)
>>> queue.put("Python")
>>> queue.put(3.14)
>>> queue.put(True)
>>> str(queue)
'1 <- 2 <- 3 <- Python <- 3.14 <- True'
"""
return " <- ".join(str(item) for item in self)
"""String representation."""
return " <- ".join(map(str, self))

def is_empty(self) -> bool:
"""
>>> queue = LinkedQueue()
>>> queue.is_empty()
True
>>> for i in range(1, 6):
... queue.put(i)
>>> queue.is_empty()
False
"""
return len(self) == 0

def put(self, item: Any) -> None:
"""
>>> queue = LinkedQueue()
>>> queue.get()
Traceback (most recent call last):
...
IndexError: dequeue from empty queue
>>> for i in range(1, 6):
... queue.put(i)
>>> str(queue)
'1 <- 2 <- 3 <- 4 <- 5'
"""
node = Node(item)
if self.is_empty():
self.front = self.rear = node
"""Check if queue is empty (O(1))."""
return self.front is None

# 🔥 Professional naming (industry standard)
def enqueue(self, item: Any) -> None:
"""Add element to rear (O(1))."""
new_node = Node(item)

if self.rear is None:
self.front = self.rear = new_node
else:
assert isinstance(self.rear, Node)
self.rear.next = node
self.rear = node

def get(self) -> Any:
"""
>>> queue = LinkedQueue()
>>> queue.get()
Traceback (most recent call last):
...
IndexError: dequeue from empty queue
>>> queue = LinkedQueue()
>>> for i in range(1, 6):
... queue.put(i)
>>> for i in range(1, 6):
... assert queue.get() == i
>>> len(queue)
0
"""
self.rear.next = new_node
self.rear = new_node

self._size += 1

def dequeue(self) -> Any:
"""Remove element from front (O(1))."""
if self.is_empty():
raise IndexError("dequeue from empty queue")
assert isinstance(self.front, Node)
node = self.front

assert self.front is not None
temp = self.front
self.front = self.front.next

if self.front is None:
self.rear = None
return node.data

self._size -= 1
return temp.data

def peek(self) -> Any:
"""Return front element without removing."""
if self.is_empty():
raise IndexError("peek from empty queue")

assert self.front is not None
return self.front.data

def clear(self) -> None:
"""
>>> queue = LinkedQueue()
>>> for i in range(1, 6):
... queue.put(i)
>>> queue.clear()
>>> len(queue)
0
>>> str(queue)
''
"""
"""Remove all elements."""
self.front = self.rear = None
self._size = 0


if __name__ == "__main__":
from doctest import testmod
q = LinkedQueue()

q.enqueue(10)
q.enqueue(20)
q.enqueue(30)

testmod()
print("Queue:", q)
print("Front:", q.peek())
print("Dequeued:", q.dequeue())
print("Queue after dequeue:", q)
Loading