Abstract Data Types (Array-Based)

Queue

A First-In-First-Out (FIFO) structure built on an array — enqueue, dequeue, the circular queue with MOD wrap-around, overflow/underflow checks, and a full exam-style question. The ADT behind print queues, keyboard buffers, and ticket systems.

18.1 What is a Queue?

If a stack is a pile of plates, a queue is a line of people at the school canteen. The first person to join the line is the first one served; newcomers join at the back. Nobody pushes in. That single rule — first in, first out (FIFO) — is what makes a queue different from a stack.

A queue keeps two pointers: front (who's next to be served) and rear (where the last person stood). You add at the rear and remove from the front.

TermMeaning
QueueAn ADT where items are added at one end (rear) and removed from the other (front). FIFO.
FIFOFirst In, First Out — the first item added is the first removed.
EnqueueAdd a new item at the rear of the queue.
DequeueRemove and return the item from the front.
FrontPointer to the index of the next item to remove.
RearPointer to the index of the last item added.
CountInteger tracking how many items are currently stored.
OverflowTrying to enqueue when the queue is full (count == MAX_SIZE).
UnderflowTrying to dequeue when the queue is empty (count == 0).
CircularUsing MOD to wrap pointers back to 0, reusing freed slots.
Your Turn — Describe a queue [3 marks]
Describe two key features of a queue and state one real situation where a queue is the right ADT.
Hint:
  • FIFO — first in, first out
  • Add at rear, remove from front
  • Use cases: print queue, ticket system, keyboard buffer

18.2 Linear vs Circular Queue

Imagine a queue stored in a list of 5 slots. You enqueue A, B, C, D, E (rear reaches index 4), then dequeue A and B (front moves to index 2). Indexes 0 and 1 are now free, but a plain "linear" queue cannot use them: the rear pointer is already at the end. The queue looks full even though two slots are empty. That is wasted space.

The fix — circular queue:
  • When a pointer would step past the last index, it wraps back to 0.
  • We do this with (pointer + 1) % MAX_SIZE.
  • If rear is 4 and MAX_SIZE is 5, then (4 + 1) % 5 = 0 — back to the start, into a freed slot.
# Circular wrap with MOD
rear = (rear + 1) % MAX_SIZE   # enqueue: wrap rear
front = (front + 1) % MAX_SIZE # dequeue: wrap front

# Example: rear = 4, MAX_SIZE = 5
# (4 + 1) % 5 = 5 % 5 = 0  -> rear wraps to index 0

# Example: front = 7, MAX_SIZE = 8
# (7 + 1) % 8 = 8 % 8 = 0  -> front wraps to index 0
Exam tip:
  • If you keep a count of items, "empty" is count == 0 and "full" is count == MAX_SIZE.
  • This avoids the tricky case where front and rear point to the same slot, which could mean either empty or full without a count.
Your Turn — Calculate the wrap [1 marks]
A circular queue has MAX_SIZE = 5 and rear = 4. Calculate the new value of rear after the next enqueue.
Hint:
  • Use (rear + 1) % MAX_SIZE
  • (4 + 1) % 5 = ?
Your Turn
A circular queue has MAX_SIZE = 8 and front = 7. Calculate the new front after a dequeue.
Hint:
  • Same rule: (front + 1) % MAX_SIZE

18.2B Interactive Simulator

Try the circular queue yourself. Set MAX_SIZE, enter a value, and click Enqueue or Dequeue. Watch the front (cyan) and rear (amber) pointers move and wrap around. Try to trigger overflow and underflow.

Interactive Simulator

Circular Queue

·
0
·
1
·
2
·
3
·
4

Status: Enqueue or Dequeue to start.

Code

1MAX_SIZE = 5; queue = [None]*MAX_SIZE
2if count == MAX_SIZE:
3 return False # overflow
4 rear = (rear + 1) % MAX_SIZE
5 queue[rear] = item; count += 1
6if count == 0:
7 return None # underflow
8 item = queue[front]
9 front = (front + 1) % MAX_SIZE
10 count -= 1; return item

18.3 enqueue() — Add at the Rear

enqueue() adds a new item at the rear of the queue. The order is: check full → move rear with MOD → store item → increment count.

MAX_SIZE = 5
queue = [None] * MAX_SIZE
front = 0          # index of the next item to remove
rear = -1          # index of the last item added
count = 0          # how many items are stored

def enqueue(item):
    global rear, count
    if count == MAX_SIZE:           # is the queue full?
        print("Queue overflow")
    else:
        rear = (rear + 1) % MAX_SIZE    # move rear, wrap if needed
        queue[rear] = item              # store the item
        count = count + 1              # one more item now
Key rule — wrap with MOD:
  • Always use rear = (rear + 1) % MAX_SIZE — never just rear = rear + 1.
  • Without MOD, the queue is linear and wastes space.
Your Turn — enqueue returning True/False [6 marks]
A circular queue (queue, rear, count, MAX_SIZE) already exists. Write enqueue(item) that returns True if stored, False if full.
Hint:
  • Check full: count == MAX_SIZE, return False
  • Else: rear = (rear + 1) % MAX_SIZE
  • queue[rear] = item, count += 1
  • Return True
  • Use global rear, count
Your Turn — join(ticket) procedure
Write a procedure join(ticket) that adds at the rear, or prints "Queue full" if full.
Hint:
  • Same shape as enqueue — a procedure that prints instead of returning

18.4 dequeue() — Remove from the Front

dequeue() removes and returns the front item. The order is: check empty → read item → move front with MOD → decrement count → return item.

def dequeue():
    global front, count
    if count == 0:                    # is the queue empty?
        return None
    else:
        item = queue[front]             # read the front item
        front = (front + 1) % MAX_SIZE  # move front, wrap if needed
        count = count - 1              # one fewer item now
        return item                     # give it back to the caller
Key rule — read before moving front:
  • Read item = queue[front] FIRST, then front = (front + 1) % MAX_SIZE.
  • If you move front first, it no longer points at the item.
Your Turn — dequeue returning -1
Write dequeue() that returns the front item, or -1 if the queue is empty.
Hint:
  • Check empty: count == 0, return -1
  • Else: read item, move front with MOD, decrement count, return
Your Turn — next_job() function
Write a function next_job() that removes and returns the front job, or returns "No jobs" if empty.
Hint:
  • Identical to dequeue — only the empty message differs

18.5 peek(), is_empty(), is_full()

def is_empty():
    return count == 0

def is_full():
    return count == MAX_SIZE

def peek():
    if is_empty():
        return None
    return queue[front]     # front item, not removed

def spaces_left():
    return MAX_SIZE - count
Key rule — count makes it unambiguous:
  • With count, empty is count == 0 and full is count == MAX_SIZE.
  • Without count, front == rear could mean either — ambiguous and dangerous.
Your Turn — spaces_left()
Write a function spaces_left() returning how many free slots remain.
Hint:
  • You are already tracking this with count
  • MAX_SIZE - count

18.6 Tracing Enqueue and Dequeue

A trace shows front, rear, and count after each operation. Remember: rear wraps with (rear + 1) % MAX_SIZE.

# MAX_SIZE = 4, start empty (front=0, rear=-1, count=0)

start      front=0 rear=-1 count=0
enqueue X  front=0 rear=0  count=1
enqueue Y  front=0 rear=1  count=2
dequeue    front=1 rear=1  count=1  (X out)
enqueue Z  front=1 rear=2  count=2
Your Turn — Trace with wrap-around
Trace: MAX_SIZE=4, start empty. enqueue P, Q, R, dequeue, dequeue, enqueue S, enqueue T. Show front, rear, count after each.
Hint:
  • enq P: f=0 r=0 c=1
  • enq Q: f=0 r=1 c=2
  • enq R: f=0 r=2 c=3
  • deq: f=1 r=2 c=2 (P out)
  • deq: f=2 r=2 c=1 (Q out)
  • enq S: f=2 r=3 c=2
  • enq T: f=2 r=0 c=3 (rear wrapped to 0!)

18.7 Full Exam-Style Question

Tarnima runs an online helpdesk. Support tickets must be answered in the order they arrive. She stores up to 6 tickets in a circular queue.

(a) — Declare and initialise [4 marks]
  • The queue is stored as a global list tickets with global integers front, rear, count and a constant MAX set to 6.
  • Write program code to declare and initialise them all (an empty queue).
Your Turn — (a) Model answer
Declare tickets (6), front, rear, count, MAX = 6. [4 marks]
Hint:
  • MAX = 6
  • tickets = [""] * MAX
  • front = 0, rear = -1, count = 0
(b) — add_ticket(ref) [6 marks]
  • Write a function add_ticket(ref) that adds a ticket at the rear.
  • Returns True if added, False if full.
Your Turn — (b) Model answer
Write add_ticket(ref) that enqueues, returns True/False. [6 marks]
Hint:
  • Check full: count == MAX, return False
  • rear = (rear + 1) % MAX
  • tickets[rear] = ref, count += 1
  • Return True
(c) — answer_next() [5 marks]
  • Write a function answer_next() that removes and returns the front ticket,
  • or returns "No tickets" if empty.
Your Turn — (c) Model answer
Write answer_next() that dequeues, or returns "No tickets". [5 marks]
Hint:
  • Check empty: count == 0, return "No tickets"
  • Read ref = tickets[front]
  • front = (front + 1) % MAX
  • count -= 1, return ref

Key Points Summary

A queue follows FIFO — First In, First Out. First item enqueued is first dequeued.
Two pointers: front (next to remove) and rear (where to add). Plus count for tracking.
Enqueue adds at rear; dequeue removes from front. Two different ends.
Linear queue wastes space: freed slots at front cannot be reused.
Circular queue fixes this: (pointer + 1) % MAX_SIZE wraps back to 0.
Setup: MAX_SIZE, array of that size, front=0, rear=-1, count=0.
enqueue order: check full → rear = (rear+1) % MAX → store → count += 1.
Overflow: count == MAX_SIZE (queue is full).
dequeue order: check empty → read item → front = (front+1) % MAX → count -= 1 → return.
Read the item BEFORE moving front — otherwise front no longer points at it.
Underflow: count == 0 (queue is empty).
Using count avoids ambiguity: count==0 means empty, count==MAX_SIZE means full.
peek() returns queue[front] without moving any pointer.
spaces_left() = MAX_SIZE - count.
Use cases: print queue, keyboard buffer, ticket system, network packets.
enqueue/dequeue must use "global rear/front, count" — they modify all three.

18.8 Practice Tasks

Fifteen exam-style queue tasks. Each shows only the question — click Hint for the thought process, or Help for the worked solution.

Exam tip:
  • For every queue task the marker checks:
  • (1) correct overflow/underflow check (count-based)
  • (2) correct MOD wrap for both pointers
  • (3) correct read-before-move in dequeue, and (4) returning the dequeued value
  • The most common mark loss is forgetting MOD (using +1 instead of (pointer+1) % MAX_SIZE).
1Practice Task — Declare a circular queue [4 marks]
Declare a circular queue of 5 items with front, rear, count, MAX_SIZE.
2Practice Task — enqueue() [6 marks]
Write enqueue(item) that adds at rear with MOD wrap, returns True/False.
3Practice Task — dequeue() [5 marks]
Write dequeue() that removes and returns the front item with MOD wrap, or None if empty.
4Practice Task — peek() [3 marks]
Write peek() that returns the front item without removing it, or None if empty.
5Practice Task — is_empty() and is_full() [2 marks]
Write is_empty() and is_full() using count.
6Practice Task — spaces_left() [2 marks]
Write spaces_left() returning free slots.
7Practice Task — Calculate wrap [1 marks]
rear = 4, MAX_SIZE = 5. Calculate new rear after enqueue.
8Practice Task — Trace enqueue/dequeue [4 marks]
Trace: MAX_SIZE=4, start empty. enqueue X, Y, dequeue, enqueue Z. Show front, rear, count.
9Practice Task — Trace with wrap [4 marks]
Trace: MAX_SIZE=4. enqueue P, Q, R, dequeue, dequeue, enqueue S, enqueue T. Show all.
10Practice Task — Describe a queue [3 marks]
Describe two key features of a queue and one real situation where it would be suitable.
11Practice Task — Why circular? [2 marks]
Explain why a circular queue is better than a linear queue.
12Practice Task — Overflow vs underflow [2 marks]
State the overflow and underflow conditions for a queue using count.
13Practice Task — Helpdesk exam question [15 marks]
(a) Declare tickets(6), front, rear, count, MAX [4]. (b) add_ticket(ref) returns True/False [6]. (c) answer_next() returns front or "No tickets" [5].
14Practice Task — Why use count? [2 marks]
Explain why a count variable is used instead of comparing front and rear.
15Practice Task — Stack vs queue [2 marks]
State one difference between a stack and a queue.

Question Bank

Answer all questions, then press Submit Quiz to see your score.

0/12 answered

Question 1Multiple Choice

What rule does a queue follow?

Question 2True / False

A circular queue uses (pointer + 1) % MAX_SIZE to wrap pointers.

Question 3Multiple Choice

What is the overflow condition?

Question 4Multiple Choice

What is the underflow condition?

Question 5True / False

enqueue adds at the rear, dequeue removes from the front.

Question 6Multiple Choice

How does rear move in enqueue?

Question 7Multiple Choice

In dequeue(), when do you read the item?

Question 8True / False

If rear = 4 and MAX_SIZE = 5, (rear + 1) % MAX_SIZE = 0.

Question 9Multiple Choice

Which is NOT a use case for a queue?

Question 10Multiple Choice

What does spaces_left() return?

Question 11True / False

Using count avoids the ambiguity of front == rear.

Question 12Multiple Choice

What does peek() return?

Answer all 12 questions to enable submission.