Skip to content
Part IA Michaelmas Term

Functional Queues

Queue ADT

A queue is a sequence with First-In-First-Out (FIFO) discipline. The item next to be removed is the one that has been in the queue the longest.

OperationDescription
qemptyThe empty queue
qnull qTest whether q is empty
qhd qReturn the element at the head
deq qDiscard the element at the head
enq q xAdd x to the tail

The two-list representation

Represent the queue x₁x₂…xₘyₙ…y₁ by a pair of lists:

([x₁; x₂; ...; xₘ], [y₁; y₂; ...; yₙ])
  • The front list is stored in order: the head of this list is the head of the queue.
  • The rear list is stored in reverse order: the head of this list is the tail of the queue.

Functional queue

Operations

type 'a queue = Q of 'a list * 'a list

Enqueue adds to the rear list using :: (O(1)):

let enq (Q (hds, tls)) x = norm (Q (hds, x :: tls))

Dequeue removes from the front list using pattern-matching (O(1) normally):

let deq = function
  | Q (x :: hds, tls) -> norm (Q (hds, tls))
  | _ -> raise Empty

Head reads from the front list:

let qhd = function
  | Q (x :: _, _) -> x
  | _ -> raise Empty

Normalisation

The function norm ensures the front list is never empty unless the queue is empty:

let norm = function
  | Q ([], tls) -> Q (List.rev tls, [])
  | q -> q

When the front list becomes empty, norm reverses the rear list, making it the new front list. This reversal takes O(n) time for a rear list of length n, but as we shall see, the amortised cost per operation is O(1).