liveBook · Manning

Queue

As explained in Fabulous Adventures in Data Structures and Algorithms

A queue is a first-in, first-out data structure supporting insertion at one end and removal at the other.

A queue is a first-in, first-out data structure: the least recently enqueued item is the next item dequeued. Its interface typically includes Enqueue, Peek, Dequeue, and IsEmpty. section 2.4

An immutable queue returns a new queue after each operation rather than changing the existing one. A linked list makes one end cheap, but efficient operations at both ends require a different arrangement. section 2.4

Build an immutable queue from two immutable stacks:

  • Store newly enqueued items in an enqueue stack. section 2.4
  • Store items ready for removal in a dequeue stack. section 2.4
  • Peek at, or pop from, the dequeue stack; when it is empty, transfer the enqueue stack into it in reversed order. section 2.4
Listing 2.6 An immutable queue interface
interface IImQueue<T> : IEnumerable<T>
{
    IImQueue<T> Enqueue(T item);
    T Peek();
    IImQueue<T> Dequeue();
    bool IsEmpty { get; }
}

Use the interface listing to inspect the compact immutable queue contract. section 2.4

Persistent queue values

Starting with the empty queue, enqueueing 10, 20, and 30 produces [10, 20, 30]. Dequeuing successively produces [20, 30], [30], and []; earlier queue values remain available for reuse. section 2.4

Listing 2.7 An immutable queue implementation
class ImQueue<T> : IImQueue<T>
{
    public static IImQueue<T> Empty { get; } = 
        new ImQueue<T>(ImStack<T>.Empty, ImStack<T>.Empty); #1
    private readonly IImStack<T> enqueues;
    private readonly IImStack<T> dequeues;
    private ImQueue(IImStack<T> enqueues, IImStack<T> dequeues)
    {
        this.enqueues = enqueues;
        this.dequeues = dequeues;
    }
    public IImQueue<T> Enqueue(T item) => 
        IsEmpty ? #2
        new ImQueue<T>(enqueues, dequeues.Push(item)) :
        new ImQueue<T>(enqueues.Push(item), dequeues);
    public T Peek() => dequeues.Peek(); #3
    public IImQueue<T> Dequeue()
    {
        IImStack<T> newdeq = dequeues.Pop(); #4
        if (!newdeq.IsEmpty)
            return new ImQueue<T>(enqueues, newdeq);
        if (enqueues.IsEmpty)
            return Empty;
        return new ImQueue<T>(ImStack<T>.Empty, enqueues.Reverse()); #5
    }
    public bool IsEmpty => dequeues.IsEmpty;
    public IEnumerator<T> GetEnumerator()
    {
        foreach (var item in dequeues)
            yield return item;
        foreach (var item in enqueues.Reverse())
            yield return item;
    }
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
static class Extensions
{
    public static IImStack<T> Reverse<T>(this IImStack<T> stack)
    {
        var result = ImStack<T>.Empty;
        for (; !stack.IsEmpty; stack = stack.Pop())
            result = result.Push(stack.Peek());
        return result;
    }
}

Use the implementation listing to trace empty-queue handling, two-stack storage, and persistent updates. section 2.4

How Fabulous Adventures in Data Structures and Algorithms covers it

How deep it goes
Develops the interface, two-stack representation, empty cases, persistence, and observable examples, but does not provide detailed complexity analysis.
Examples
Uses C# interface and implementation listings plus successive queue values [10, 20, 30], [20, 30], [30], and [].
What it assumes
Assumes familiarity with stacks and linked lists while defining the queue interface and immutable behavior explicitly.
What you can do after
Build an immutable queue in C# using two immutable stacks and persistent enqueue and dequeue operations.
How it connects
Connects queues to immutable stacks, linked lists, persistence, and functional-style immutable data structures.

Also explained in

Compare how 24 books explain queue →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Fabulous Adventures in Data Structures and Algorithms. The section links point to the parts of the book it draws on.