Computational Thinking and Data Structures: Question 8

Syllabus 10.4

Structured AS 10 marks

A university's network print server must process print jobs from students in the exact order they are submitted: the job submitted first must always be printed first.

(a) State which abstract data type, a stack or a queue, should be used to store the waiting print jobs so that they are processed in the order described above, and justify your answer by referring to the order in which jobs are added and removed. [2]

(b) The print server implements this abstract data type, named PrintQueue, using a 1D array of up to 5 elements, DECLARE PrintQueue : ARRAY[1:5] OF STRING, together with two integer pointer variables: Front (the array index of the job at the front of the queue, next to be printed) and Rear (the array index of the job most recently added). Both Front and Rear start at 0, meaning PrintQueue is empty. Starting from this empty state, the following operations occur, in order:

  • ENQUEUE "Report1"
  • ENQUEUE "Report2"
  • ENQUEUE "Report3"
  • DEQUEUE
  • ENQUEUE "Report4"
  • DEQUEUE

Complete a trace table showing the value of Front, the value of Rear, and the contents of PrintQueue after each of these six operations. [5]

(c) State which print job would be produced if DEQUEUE were called one more time, immediately after the six operations above. [1]

(d) Front and Rear in this implementation only ever increase, they never wrap back around to the start of the array. State one limitation this causes, illustrating your answer with a specific example based on the array PrintQueue. [2]

Show worked solution Hide worked solution

Worked solution

Part (a): Stack or queue?

Print jobs must be printed in the exact order they are submitted: the job submitted first must always be printed first. This is a first-in, first-out (FIFO) access pattern. The earliest job added is the first one removed. That is precisely the defining behaviour of a queue.

A stack would be the wrong choice here, because a stack is last-in, first-out (LIFO). It would print the most recently submitted job first, which does not match the order described.

[2 marks]: [1] for stating “queue”, [1] for justifying it with reference to FIFO order (the job waiting longest is removed first).

Part (b): Tracing ENQUEUE and DEQUEUE with Front and Rear

ENQUEUE increases Rear by 1 and stores the new value at PrintQueue[Rear] (and, if the queue was previously empty, also sets Front to 1). DEQUEUE reads the value currently at PrintQueue[Front] and then increases Front by 1.

OperationFrontRearContents of PrintQueue (front → rear)
ENQUEUE "Report1"11[Report1]
ENQUEUE "Report2"12[Report1, Report2]
ENQUEUE "Report3"13[Report1, Report2, Report3]
DEQUEUE23[Report2, Report3]. “Report1” is removed
ENQUEUE "Report4"24[Report2, Report3, Report4]
DEQUEUE34[Report3, Report4]. “Report2” is removed

Note that after each DEQUEUE, the array position itself still physically holds the old value (for example, PrintQueue[1] still holds “Report1” after the fourth row). It is simply no longer part of the logical queue, because Front has moved past it.

[5 marks]: [1] for the correct value of Front after each of the six operations, [1] for the correct value of Rear after each of the six operations, [1] for the correct contents after the three ENQUEUE operations, [1] for correctly removing the job that has been waiting longest on each DEQUEUE (not the most recently added job), [1] for the final state Front = 3, Rear = 4, PrintQueue logically containing [Report3, Report4].

Part (c): One more DEQUEUE

After the six operations, Front = 3, so PrintQueue[Front] is PrintQueue[3] = "Report3". Calling DEQUEUE once more produces “Report3”, and Front would then increase to 4. [1 mark]

Part (d): A limitation of Front and Rear that never wrap around

Because Front and Rear only ever increase and never wrap back around to reuse positions freed by earlier DEQUEUE operations, those freed positions become permanently unusable. In this example, after the six operations Front = 3 and Rear = 4, so array positions 1 and 2 are free but can never be written to again. Only one further ENQUEUE is possible. Rear can still become 5, which is a valid index in ARRAY[1:5], but a second further ENQUEUE after that would need Rear to become 6, which is outside the declared array bounds. The queue would therefore report itself as full and reject a new print job, even though positions 1 and 2 are genuinely free and could have stored it. [2 marks]: [1] for identifying that freed positions at the start of the array can never be reused, [1] for a concrete illustrative example (using the actual index values from this scenario) showing the queue incorrectly reporting itself as full.

Final answers

  • (a) A queue. FIFO order matches “job submitted first is printed first”.
  • (b) See the trace table above; final state after all six operations: Front = 3, Rear = 4, PrintQueue logically containing [Report3, Report4].
  • (c) “Report3” is produced; Front becomes 4.
  • (d) Freed positions at the start of the array (indices 1 and 2 here) can never be reused, so the queue can incorrectly report itself as full. For example, after only one more ENQUEUE (Rear = 5), a further ENQUEUE would need Rear = 6, outside ARRAY[1:5].