Problem
Implementing a queue using a linked list.
Examples
Example 1:
Input:
Operations: ["enqueue(1)", "enqueue(2)", "front()", "dequeue()", "isEmpty()"]
Output: [null, null, 1, 1, false]
Explanation:
1. Enqueue 1: The queue becomes [1].
2. Enqueue 2: The queue becomes [1, 2].
3. Front: The front element is 1.
4. Dequeue: Remove the front element 1. The queue becomes [2].
5. isEmpty: The queue is not empty, hence returns false.
Solution
Method 1 - Using Linked list
A linked list is an ideal data structure for implementing a queue because it allows efficient addition and removal of elements at both ends. We will use a singly linked list to create the queue, where each node holds a value and a reference to the next node. We maintain pointers to both the front (head) and the rear (tail) of the queue to ensure all operations are efficient.
To make removing the last item from the queue easy, the queue should use a doubly linked list.
Here is the approach:
- Node Class: Create a Node class that stores data and a reference to the next node.
- Queue Class: Implement the queue using the Node class with pointers to the head and tail nodes.
- enqueue(x): Add a new node at the tail or rear point.
- dequeue(): Remove the node from the head or front.
- isEmpty(): Check if the head or front is null.
- front(): Return the value of the head or front node.
The Enqueue method simply adds a new cell to the top of the list, and the Dequeue method removes the bottom cell from the list.
Code
Java
class Solution {
private ListNode head, tail;
public Solution() {
head = null;
tail = null;
}
public void enqueue(int x) {
ListNode newNode = new ListNode(x);
if (tail == null) {
head = tail = newNode;
} else {
tail.next = newNode;
tail = newNode;
}
}
public int dequeue() {
if (isEmpty()) {
throw new IllegalStateException("Queue is empty");
}
int value = head.val;
head = head.next;
if (head == null) {
tail = null;
}
return value;
}
public boolean isEmpty() {
return head == null;
}
public int front() {
if (isEmpty()) {
throw new IllegalStateException("Queue is empty");
}
return head.val;
}
}
Python
class ListNodeQueue:
def __init__(self):
self.rear = None
self.front = None
self.count = 0
# Insert at the rear
def enqueue(self, item: int) -> bool:
node = ListNode(item)
if self.front is None:
self.front = node
self.rear = node
else:
self.rear.next = node
self.rear = node
self.count += 1
return True
# Delete at the beginning
def dequeue(self) -> int:
if self.is_empty():
raise IndexError("Queue is empty")
temp = self.front
self.front = self.front.next
# If the list becomes empty
if self.front is None:
self.rear = None
self.count -= 1
return temp.val
def peek(self) -> int:
if self.is_empty():
raise IndexError("Queue is empty")
return self.front.val
def is_empty(self) -> bool:
return self.count == 0 # We can also do: rear == None and front == None
def size(self) -> int:
return self.count