tl;dr: Use Circular queues. They are space efficient (they reuse the space in the array) and time efficient O(1).
- Queue - Implemented Using Array & 1 pointer
- Queue - Implemented Using Array & 2 pointers
- Circular Queue - Implementated using Arrays
- Doubly Ended Queues (DEQueue) - Implemented using Arrays
- Priority Queues (Fixed number of priorities) - Implemented using Arrays
- Priority Queues (Infinite priorities) - Implemented using Arrays
Criteria | 1P Queue (1 Pointer Queue) | 2P Queue (2 Pointers Queue) | Circular Queue |
---|---|---|---|
Space Utilized | Efficient (✓) | Less Efficient (X) | Efficient (✓) |
Implemented With | Arrays | Linked List | Arrays |
Server Moves | No (X) | Yes (✓) | Yes (✓) |
Element Moves | Yes (✓) | No (X) | No (X) |
Space Complexity | O(n) - Requires space proportional to the number of elements | O(n) - Requires space proportional to the number of elements | O(n) - Requires space proportional to the number of elements |
Time Complexity | |||
- Enqueue | O(1) - Adding an element at the end is constant time | O(1) - Adding an element is constant time with two pointers | O(1) - Adding an element is constant time |
- Dequeue | O(1) - Removing an element from the front is constant time | O(1) - Removing an element is constant time with two pointers | O(1) - Removing an element is constant time |
Ease of Implementation | Simple - Easy to implement using arrays | Moderate - Requires handling two pointers and linked list structures | Moderate - Requires managing the circular nature |
Examples | - Docks - Goods-to-man packing process - Conveyor belt systems - Loading/unloading docks |
- Robotic picking systems - Forklift routes in a warehouse - Order picking by humans moving to items |
- Circular conveyor belts - Carousel storage systems - Automated guided vehicles (AGVs) in a circular path |
- Interface:
queue.h
- Program:
queue_arr_1p.c
Function Name | Description | Time Complexity | Space Complexity |
---|---|---|---|
queue_init | Initializes the queue with specified type and size | O(1) | O(n) |
queue_destroy | Destroys the queue, freeing allocated memory | O(1) | O(1) |
queue_enqueue | Enqueues an element to the queue | O(1) | O(1) |
queue_dequeue | Dequeues an element from the queue | O(n) | O(1) |
queue_isEmpty | Checks if the queue is empty | O(1) | O(1) |
queue_isFull | Checks if the queue is full | O(1) | O(1) |
queue_peek | Returns element after index 0 (1P) / front pointer (2P) | O(1) | O(1) |
queue_count_elements | Returns total count of elements left in queue | O(1) | O(1) |
Notes
- rear pointer: intially at -1 (before index 0).
- insertion: at rear. O(1)
- deletion: remove first element. Move all elements to front. O(n)
- Interface:
queue.h
- Program:
queue_arr_2p.c
Function Name | Description | Time Complexity | Space Complexity |
---|---|---|---|
queue_init | Initializes the queue with specified type and size | O(1) | O(n) |
queue_destroy | Destroys the queue, freeing allocated memory | O(1) | O(1) |
queue_enqueue | Enqueues an element to the queue | O(1) | O(1) |
queue_dequeue | Dequeues an element from the queue | O(n) | O(1) |
queue_isEmpty | Checks if the queue is empty | O(1) | O(1) |
queue_isFull | Checks if the queue is full | O(1) | O(1) |
queue_peek | Returns element after index 0 (1P) / front pointer (2P) | O(1) | O(1) |
queue_count_elements | Returns total count of elements left in queue | O(1) | O(1) |
Notes
- 2 pointers: front & rear. Both at -1.
- insertion: increment rear pointer. move rear to next location. insert element. O(1)
- deletion: increment front pointer. delete element. O(1). Front pointer needs to be BEFORE the first element!
- isEmpty: when front pointer = rear pointer (anywhere in the queue array)
- isFull: when rear pointer = size of array - 1. (This mean front pointer could be either at -1 or somewhere in the middle ... )
- Can have condition isFull & isEmpty at same time (when rear pointer is at end, and front pointer is rear - 1).
- isFull: Full size of array is not used if rear = end of array & front != -1. We cannot reuse the space of deleted elements. Every array location can only be used once! Queue can be full and empty at same time.
- Resetting pointers: if queue becomes empty (front & rear have same index), then reinitialize pointers to -1.
- Circular queues
- Clock analogy: 12-hour clock face represents modulo 12 arithmetic
- Modulo operation "wraps around" when reaching the divisor
- Examples (modulo 12):
- 12 % 12 = 0
- 3 % 12 = 3
- 14 % 12 = 2
- 25 % 12 = 1
- Pattern: For n and positive divisor d, n % d results in [0, d-1]
- Pointer to array
- Array size
- Front pointer
- Rear pointer
- Queue length
- Initialization: Front and rear pointers start at index 0
- Capacity:
- Max elements: N-1 (for array size N)
- Full when containing N-1 elements
- Front pointer always points to empty position
- Front and rear pointers coincide only when empty
- Distinguishes between full and empty states
- Enqueue (while not full):
- Move rear:
r = (r + 1) % size
- Insert at new rear index
- Move rear:
- Dequeue (while not empty):
- Move front:
f = (f + 1) % size
- Move front:
- Check Empty:
- Empty
if front == rear
- Empty
- Check Full:
- Full
if (r + 1) % size == front
- Full
- Use modulo for pointer wraparound
- Visualize as clock face for wraparound behavior