Queue Implementation Using Linked List in DSA Java - Time & Space Complexity
We want to understand how fast the main actions of a queue using a linked list happen as the queue grows.
How does adding or removing items take more or less time when the queue gets bigger?
Analyze the time complexity of the following code snippet.
public class Queue {
private Node front, rear;
private static class Node {
int data;
Node next;
Node(int d) { data = d; next = null; }
}
public void enqueue(int item) {
Node newNode = new Node(item);
if (rear == null) {
front = rear = newNode;
return;
}
rear.next = newNode;
rear = newNode;
}
public int dequeue() {
if (front == null) return -1;
int value = front.data;
front = front.next;
if (front == null) rear = null;
return value;
}
}
This code adds items to the end and removes items from the front of a queue using a linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Adding or removing one node at a time without loops.
- How many times: Each enqueue or dequeue runs once per call, no loops inside.
Each add or remove action takes the same small steps no matter how many items are in the queue.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 5-6 steps |
| 100 | 5-6 steps |
| 1000 | 5-6 steps |
Pattern observation: The time to add or remove does not grow with the queue size; it stays constant.
Time Complexity: O(1)
This means adding or removing an item takes the same short time no matter how big the queue is.
[X] Wrong: "Removing an item takes longer as the queue grows because you have to move through all nodes."
[OK] Correct: The queue keeps track of the front node, so removing just changes a pointer without walking through the list.
Knowing that queue operations are constant time shows you understand efficient data structure design, a key skill in many coding challenges.
"What if we used a singly linked list without a rear pointer? How would the time complexity of enqueue change?"
Practice
Solution
Step 1: Understand queue size limitation in arrays
Arrays have fixed size, so queues implemented with arrays have a maximum capacity.Step 2: Linked list allows dynamic size
Linked lists can grow or shrink as needed, so queues using linked lists have no fixed size limit.Final Answer:
Dynamic size, no fixed limit on queue length -> Option AQuick Check:
Linked list queue size = dynamic [OK]
- Thinking arrays always use less memory
- Confusing access speed with size flexibility
- Assuming linked lists are simpler to implement
Solution
Step 1: Identify node fields for linked list queue
A node should store data and a reference to the next node.Step 2: Check each option's correctness
class Node { int data; Node next; } has int data and Node next, which is correct. Others have incorrect types or missing next pointer.Final Answer:
class Node { int data; Node next; } -> Option DQuick Check:
Node stores data + next pointer [OK]
- Using 'prev' pointer instead of 'next' for queue node
- Declaring next as int instead of Node
- Using Node type for data field
Queue q = new Queue(); q.enqueue(10); q.enqueue(20); q.dequeue(); q.enqueue(30); q.display();
Assuming
display() prints elements front to rear separated by ' -> ' and ends with ' -> null'.Solution
Step 1: Trace enqueue and dequeue operations
Enqueue 10: queue = 10
Enqueue 20: queue = 10 -> 20
Dequeue: removes 10, queue = 20
Enqueue 30: queue = 20 -> 30Step 2: Display queue elements
Queue elements front to rear are 20 followed by 30, so output is '20 -> 30 -> null'.Final Answer:
20 -> 30 -> null -> Option AQuick Check:
After dequeue, front is 20, then 30 [OK]
- Not removing the first element on dequeue
- Appending new elements at front instead of rear
- Confusing order of elements in display
public int dequeue() {
if (front == null) {
System.out.println("Queue is empty");
return -1;
}
int value = front.data;
front = front.next;
if (front == null) {
rear = null;
}
return value;
}Solution
Step 1: Check empty queue handling
Method checks if front is null and returns -1 with message, which is correct.Step 2: Check updating front and rear pointers
After removing front node, front is updated to next node. If front becomes null, rear is also set to null. This is correct to keep queue consistent.Final Answer:
No error, method works correctly -> Option BQuick Check:
Dequeue updates front and rear properly [OK]
- Not setting rear to null when queue becomes empty
- Returning wrong value after dequeue
- Not checking for empty queue before dequeue
reverseQueue() that reverses the order of elements in a linked list queue without using extra data structures. Which approach is best?Solution
Step 1: Understand constraints
We cannot use extra data structures like stack or new linked list, so options C and D are invalid.Step 2: Evaluate remaining options
Traverse linked list and swap data of front and rear nodes repeatedly swaps data repeatedly but is inefficient and complex. Use recursion to dequeue elements and enqueue them back in reverse order uses recursion to dequeue all elements, then enqueue them back in reverse order, effectively reversing the queue without extra structures.Final Answer:
Use recursion to dequeue elements and enqueue them back in reverse order -> Option CQuick Check:
Recursion reverses queue without extra structures [OK]
- Using extra data structures despite constraints
- Trying to swap node data instead of rearranging nodes
- Not handling empty or single-element queue cases
Ready to prove it?
Pass the test and this pattern moves unknown
