Yes. Ignore the pseudocode for a moment. The main thing you need to understand is what a queue is. Once that clicks, both Question 2 and Question 3 are basically the same operation stored in two different ways.

0. What even is a queue?

Think of an actual queue at a food stall:

FRONT                           REAR
  ↓                               ↓
[Alice] → [Bob] → [Charlie] → [David]

leaves                            joins
here                              here

A queue follows:

FIFO = First In, First Out

Alice joined first, so Alice leaves first.

There are only 2 operations you need to know:

OperationMeaningWhere?
EnqueueAdd an itemREAR
DequeueRemove an itemFRONT

So memorise:

ENQUEUE → REAR
DEQUEUE → FRONT


Question 2 — Queue using an ARRAY

The question says:

A queue is held in an array q[1] to q[n].

Suppose n = 5.

Initially:

Array position:
       1     2     3     4     5
     ┌─────┬─────┬─────┬─────┬─────┐
q    │     │     │     │     │     │
     └─────┴─────┴─────┴─────┴─────┘

COUNT = 0

Now enqueue "A":

       1     2     3     4     5
     ┌─────┬─────┬─────┬─────┬─────┐
q    │  A  │     │     │     │     │
     └─────┴─────┴─────┴─────┴─────┘
       ↑
     FRONT
       ↑
      REAR

Enqueue "B":

       1     2     3     4     5
     ┌─────┬─────┬─────┬─────┬─────┐
q    │  A  │  B  │     │     │     │
     └─────┴─────┴─────┴─────┴─────┘
       ↑     ↑
     FRONT  REAR

Enqueue "C":

       1     2     3     4     5
     ┌─────┬─────┬─────┬─────┬─────┐
q    │  A  │  B  │  C  │     │     │
     └─────┴─────┴─────┴─────┴─────┘
       ↑           ↑
     FRONT        REAR

Now dequeue.

Remember:

dequeue removes from the FRONT

So "A" comes out.

       1     2     3     4     5
     ┌─────┬─────┬─────┬─────┬─────┐
q    │     │  B  │  C  │     │     │
     └─────┴─────┴─────┴─────┴─────┘
             ↑     ↑
           FRONT  REAR

Notice something important:

We do NOT need to move B and C.

We simply move the FRONT pointer.


But there is a problem

Suppose we continue.

After using the queue for a while:

       1     2     3     4     5
     ┌─────┬─────┬─────┬─────┬─────┐
q    │     │     │  C  │  D  │  E  │
     └─────┴─────┴─────┴─────┴─────┘
                   ↑           ↑
                 FRONT        REAR

There are empty spaces at positions 1 and 2.

But REAR is already at position 5.

Should we say:

“Oops, queue is full”?

No! There are two empty spaces.

So we make the array behave like a circle.


Circular queue

Imagine:

1 → 2 → 3 → 4 → 5
↑                 ↓
└─────────────────┘

After position 5, we go back to position 1.

So if REAR = 5 and another item is added:

REAR becomes 1

For example:

       1     2     3     4     5
     ┌─────┬─────┬─────┬─────┬─────┐
q    │  F  │     │  C  │  D  │  E  │
     └─────┴─────┴─────┴─────┴─────┘
       ↑           ↑
     REAR        FRONT

The logical queue is:

C → D → E → F

Even though physically it looks weird in the array.

This is a circular queue.


What variables do we need?

Use three pieces of information:

FRONT = position of first item
REAR  = position of last item
COUNT = number of items currently in queue

COUNT is especially useful because:

COUNT = 0     → queue EMPTY
COUNT = n     → queue FULL

This directly deals with the errors mentioned in the question.


Question 2(a): Adding an item

Before worrying about pseudocode, think in English.

When adding an item:

1. Check whether queue is full.
2. If full → error.
3. Otherwise move REAR to next position.
4. If REAR goes beyond n, wrap around to 1.
5. Put the new item there.
6. Increase COUNT.

That’s the entire algorithm.

Pseudocode

Suppose initially:

FRONT ← 1
REAR ← 0
COUNT ← 0

Then enqueue:

IF COUNT = n THEN
    OUTPUT "Queue is full"
ELSE
    REAR ← REAR + 1

    IF REAR > n THEN
        REAR ← 1
    ENDIF

    q[REAR] ← item
    COUNT ← COUNT + 1
ENDIF

Don’t memorise those lines individually yet.

Understand the shape:

check full
    ↓
move rear
    ↓
wrap around if necessary
    ↓
insert item
    ↓
count + 1

Question 2(b): Removing an item

Again, first do it in English.

1. Check whether queue is empty.
2. If empty → error.
3. Otherwise take the item at FRONT.
4. Move FRONT forward.
5. If FRONT goes beyond n, wrap back to 1.
6. Decrease COUNT.

Pseudocode:

IF COUNT = 0 THEN
    OUTPUT "Queue is empty"
ELSE
    item ← q[FRONT]

    FRONT ← FRONT + 1

    IF FRONT > n THEN
        FRONT ← 1
    ENDIF

    COUNT ← COUNT - 1
ENDIF

The pattern you should notice

Compare the two:

ADD

check FULL
move REAR
add item
COUNT + 1

REMOVE

check EMPTY
take FRONT item
move FRONT
COUNT - 1

That is much easier to memorise.


Question 3 — Queue using a LINKED LIST

Now we change how the queue is stored.

The queue itself has not changed.

It is still:

enqueue → rear

dequeue → front

The only difference is that instead of an array:

q[1] q[2] q[3] q[4] ...

we use nodes.


What is a linked-list node?

Each node contains two things:

┌──────────┬──────────┐
│   DATA   │   NEXT   │
└──────────┴──────────┘

For example:

┌─────┬─────┐     ┌─────┬─────┐     ┌─────┬──────┐
│  A  │  •──┼────→│  B  │  •──┼────→│  C  │ NULL │
└─────┴─────┘     └─────┴─────┘     └─────┴──────┘

NEXT tells you where the next node is.


Question 3(a)

Draw a diagram to show how a queue can be implemented using a linked list.

We simply add two pointers:

  • FRONT
  • REAR
FRONT                                      REAR
  │                                          │
  ↓                                          ↓
┌─────┬─────┐     ┌─────┬─────┐     ┌─────┬──────┐
│  A  │  •──┼────→│  B  │  •──┼────→│  C  │ NULL │
└─────┴─────┘     └─────┴─────┘     └─────┴──────┘

The queue is:

A → B → C

Who leaves next?

A, because A is at FRONT.

Where will D be added?

After C, because C is the REAR.


Why do we keep both FRONT and REAR?

Because we need to do this:

REMOVE                           ADD
  ↓                               ↓
FRONT                           REAR
  ↓                               ↓
[A] → [B] → [C] → [D]

So:

Front tells us where to delete.
Rear tells us where to insert.

This is basically the entire idea behind Question 3.


Question 3(b)(i): Add an item

Let’s say we currently have:

FRONT                         REAR
  ↓                             ↓
[A] ─────→ [B] ─────→ [C] ─────→ NULL

We want to enqueue D.

First create:

[D] → NULL

Then make C point to D:

[A] → [B] → [C] → [D] → NULL

Finally move REAR:

FRONT                                 REAR
  ↓                                     ↓
[A] ─────→ [B] ─────→ [C] ─────→ [D] → NULL

So conceptually:

1. Create new node.
2. Put item inside it.
3. Its NEXT is NULL.
4. Make current REAR point to it.
5. Move REAR to new node.

There is one special case: empty queue

Suppose the queue starts empty:

FRONT → NULL
REAR  → NULL

Then you enqueue A.

There’s no existing rear node that can point at A.

So both pointers simply become A:

FRONT
  ↓
[A] → NULL
  ↑
REAR

This gives us the algorithm:

Create NEWNODE
NEWNODE.DATA ← item
NEWNODE.NEXT ← NULL

IF FRONT = NULL THEN
    FRONT ← NEWNODE
    REAR ← NEWNODE
ELSE
    REAR.NEXT ← NEWNODE
    REAR ← NEWNODE
ENDIF

Don’t memorise it as random commands.

Think:

NEW NODE
   ↓
Is queue empty?
   ↓
 YES                    NO
 ↓                       ↓
front = new             old rear → new
rear = new              rear = new

Question 3(b)(ii): Remove an item

Suppose:

FRONT                         REAR
  ↓                             ↓
[A] ─────→ [B] ─────→ [C] ─────→ NULL

We dequeue.

Who gets removed?

A.

So first get its value:

item = A

Then move FRONT to the next node.

Before:

FRONT
  ↓
[A] → [B] → [C]

After:

       FRONT
         ↓
[A]    [B] → [C]

Then delete A:

FRONT             REAR
  ↓                 ↓
[B] ─────→ [C] ─────→ NULL

So conceptually:

1. Check whether queue is empty.
2. Take item from FRONT.
3. Move FRONT to FRONT's next node.
4. Delete old front.

Pseudocode:

IF FRONT = NULL THEN
    OUTPUT "Queue is empty"
ELSE
    TEMP ← FRONT
    item ← FRONT.DATA

    FRONT ← FRONT.NEXT

    DELETE TEMP
ENDIF

One final special case

Imagine there is only one node:

FRONT
  ↓
[A] → NULL
  ↑
REAR

Remove A.

Now:

FRONT → NULL

But REAR must also become NULL.

Otherwise REAR would still point to an item that doesn’t exist.

So the complete algorithm is:

IF FRONT = NULL THEN
    OUTPUT "Queue is empty"
ELSE
    TEMP ← FRONT
    item ← FRONT.DATA

    FRONT ← FRONT.NEXT

    IF FRONT = NULL THEN
        REAR ← NULL
    ENDIF

    DELETE TEMP
ENDIF

The BIG picture — compare Q2 and Q3

This is what I want you to internalise rather than memorising two completely separate topics.

Array QueueLinked-list Queue
Addat REARat REAR
Removefrom FRONTfrom FRONT
Full?COUNT = nUsually only if memory runs out
Empty?COUNT = 0FRONT = NULL
Enqueuemove rear + insertattach new node to rear
Dequeuetake front + move frontdelete front node

So the queue logic never changes.

Only the storage changes.


The two exam techniques to memorise

If tomorrow I gave you a blank sheet and asked both questions, start by writing:

QUEUE = FIFO

ADD    → REAR
REMOVE → FRONT

Then:

If it’s an ARRAY

ENQUEUE:
check FULL
→ move REAR
→ insert
→ count + 1

DEQUEUE:
check EMPTY
→ take FRONT
→ move FRONT
→ count - 1

If it’s a LINKED LIST

ENQUEUE = INSERT AT TAIL

DEQUEUE = DELETE AT HEAD

That last line is especially useful because you’ve already seen linked lists:

Queue implemented with linked list = insert at tail + delete at head.

If you understand that sentence, you understand about 80–90% of Question 3.