FIFO queue 2026-10-13
A FIFO queue is a data structure with first-in, first-out behavior:
enqueue inserts at the rear, dequeue removes and returns the front, and peek inspects the front without removing it. Removal and inspection require a nonempty FIFO queue, or an explicitly defined empty-case result. Enqueue in that order, dequeue , then enqueue : the remaining sequence is , with next. A LIFO stack would remove the most recently inserted item instead. A FIFO queue models arrival-order service and supplies the next vertex for breadth-first search; a stochastic service model belongs to queueing theory. [ref]https://raw.githubusercontent.com/kevin-wayne/algs4/master/src/main/java/edu/princeton/cs/algs4/Queue.java. Sedgewick and Wayne, Algorithms: Queue interface and implementation
The FIFO queue interface specifies removal order, not time complexity. A linked list with both front and rear pointers supports
enqueue, dequeue and peek in worst-case time under constant-cost pointer operations and allocation, as in Sedgewick and Wayne's implementation. A plain array that deletes its first entry by shifting the remaining entries takes time per such removal. An array with advancing front and rear indices can avoid these shifts; storage and resizing policies still need analysis. The two-list functional queue gives a different implementation with constant amortized analysis cost along a single sequence of uses. These representation choices matter when deriving the linear time complexity of breadth-first search in Big O notation.// Destination: computer-science.bigb
Information hiding 2026-10-13
Information hiding makes an implementation decision the responsibility of one software module, whose API lets other code work without knowing that decision. For a FIFO queue, clients need the removal order and failure behavior; they need not know the current front index in an array. This explains why encapsulation is useful beyond object-oriented programming: procedures with hidden storage can provide the same boundary.[ref]
On the Criteria To Be Used in Decomposing Systems into Modules by D. L. Parnas. Parnas, pp. 1054 and 1056, What Is Modularization? and The Criteria: responsibility assignments and hidden design decisions
In On the Criteria To Be Used in Decomposing Systems into Modules by D. L. Parnas (December 1972, pp. 1054–1056), the example applies a sorting algorithm to word rotations of input lines. One decomposition shares storage layouts among processing stages. The alternative exposes line-storage operations such as
CHAR and SETCHAR, hiding whether characters are packed four to a machine word. Changing that packing then belongs to line storage rather than every client. The paper presents a design argument using a deliberately small example, not a universal measured speedup or a claim that classes are required. It also notes that an unnecessarily specified rotation order restricts future implementations (p. 1056, Improvement in Circular Shift Module). Kahn's algorithm 2026-10-14
Kahn's algorithm maintains each remaining vertex's indegree, the number of its unfinished incoming directed edges, and a FIFO queue of ready vertices. Initialize the counts by scanning all directed edges and enqueue every vertex of indegree zero. Repeatedly dequeue a vertex , append it to the output, and decrement the count of each destination in 's adjacency list. Enqueue exactly when its count becomes zero. When the FIFO queue empties, accept the output if it contains all vertices; otherwise report a directed cycle. [ref]
https://raw.githubusercontent.com/kevin-wayne/algs4/master/src/main/java/edu/princeton/cs/algs4/TopologicalX.java. Sedgewick and Wayne, TopologicalX: queue-based topological sorting
Computed ready-queue trace and the obstruction caused by a reverse dependency
. Details. In the displayed run, initialize the FIFO queue as and visit 's destinations in the order . Removing makes ready but leaves waiting for . Removing then makes ready. Publication becomes ready only after both and are removed. The output is ; choosing ready vertices differently can produce the other topological orders. For the modified directed graph with , the same procedure emits and then stops with still waiting on each other.
The invariant is that each stored indegree counts incoming directed edges from unprocessed vertices. A ready vertex therefore has every prerequisite already in the output. If the FIFO queue empties with vertices left, every remaining vertex has a predecessor in the remaining directed graph; the predecessor argument gives a directed cycle. The unprocessed vertices can also include tasks blocked downstream of a directed cycle, so the leftover list alone is not a list of exactly the cyclic vertices.
With adjacency lists, constant-time array access and counter updates, and constant-time FIFO queue operations, the time complexity is in Big O notation. Initialization scans all vertices and directed edges; each vertex is then enqueued at most once and each outgoing directed edge processed at most once. Counts, ready FIFO queue, and output need storage beyond the adjacency lists. Shifting an array on every dequeue invalidates this bound. [ref]
https://raw.githubusercontent.com/kevin-wayne/algs4/master/src/main/java/edu/princeton/cs/algs4/TopologicalX.java. Sedgewick and Wayne, TopologicalX: time and extra-space bounds
[ref]https://raw.githubusercontent.com/kevin-wayne/algs4/master/src/main/java/edu/princeton/cs/algs4/Digraph.java. Sedgewick and Wayne, Digraph: adjacency lists and outgoing-edge iteration
The name refers to A. B. Kahn's 1962 paper "Topological sorting of large networks", published in Communications of the ACM, volume 5, issue 11, pages 558–562. Its abstract motivates topological sorting through network analysis and project planning. [ref]
https://doi.org/10.1145/368996.369025. Kahn, Topological sorting of large networks (1962): publisher's record and abstract
// Target: foundations-of-mathematics.bigb
Linked list 2026-10-13
A data structure representing a sequence through linked list nodes and links between them. In the singly linked representation used here, each linked list node holds an item and a
next reference to its successor. head identifies the first linked list node; the final next is null, meaning no successor. An empty linked list has head = null. Sedgewick and Wayne use this representation to implement both a stack and a FIFO queue. [ref]https://algs4.cs.princeton.edu/13stacks/index.php. Sedgewick and Wayne, Algorithms, section 1.3: linked lists
For , place the linked list nodes at conceptual computer memory positions , respectively. These deliberately separated labels describe a toy layout, not actual pointer values. The sequence order comes from the links, not increasing positions. To read index , begin at
head and follow two next references. For index , this takes link-following steps and time complexity, hence in the worst case for linked list nodes, under the constant-cost operations assumed for the array example. [ref]https://opendatastructures.org/ods-java/3_Linked_Lists.html. Pat Morin, Open Data Structures, chapter 3: links versus indexed access
Suppose a reference to the existing linked list node is already known. To insert a fresh linked list node after it, first set
X.next = B.next, preserving the old successor , and then set B.next = X. The result is ; none of the old items moves. Reversing these assignments would read the newly changed B.next and set X.next = X, losing the route to from head. This is a two-update algorithm correctness argument, rather than a claim that finding the insertion location is free.The two pointer updates take time in Big O notation. The complete insertion has time complexity if the predecessor is already known, allocating and initializing the fixed-size linked list node costs , and copying its item has constant cost. Finding from
head can instead cost ; a position described only by an index does not confer the constant-cost advantage. This makes a linked list useful when an algorithm already holds the needed linked list node, or repeatedly works at the front as a stack does.Deletion similarly needs the incoming link: to remove after known , set
B.next = X.next. A reference to alone does not identify its predecessor in this singly linked representation. The head is a special case: after checking for a nonempty linked list, remove it with head = head.next. If a tail reference is also maintained, deleting the only linked list node must clear that reference too; a stored length must also be updated. Removing a linked list node from the sequence and reclaiming its storage are separate responsibilities. [ref]https://opendatastructures.org/ods-java/3_1_SLList_Singly_Linked_Li.html. Pat Morin, Open Data Structures, section 3.1: head removal and empty-list bookkeeping
There are practical costs beyond Big O notation. Each singly linked linked list node needs a successor reference in addition to its item; separate allocation may add further overhead, while an array can reserve unused capacity. Consecutive array slots can make a scan reuse nearby contents already brought into a memory cache; separated linked list nodes can make link following wait for successive computer memory fetches. These are layout-dependent effects, not a guarantee that every array operation beats every linked list operation on every machine. An array of references can still lead to scattered objects, and linked list nodes can be allocated close together. [ref]
https://people.freebsd.org/~lstewart/articles/cpumemory.pdf. Ulrich Drepper, What Every Programmer Should Know About Memory, sections 3.3 and 6.2: access patterns and cache use
Neighbour enumeration 2026-10-14
Neighbour enumeration reports the neighbours of a specified vertex. For a simple graph, scan its adjacency list and report each entry. With constant-time list access and work per entry, a list of length needs time in Big O notation, conventionally written for nonempty lists. Use vertex degree for an undirected graph and outdegree for a directed graph. Obtaining the list reference can take constant time; consuming it requires visiting every entry.[ref]
Digraph.java. Digraph.java, class documentation and adj: obtaining the collection versus iterating in time proportional to outdegree
In our undirected example, enumerating 's neighbours reads : three entries. Scanning row of the full adjacency matrix reads six entries, , to produce the same answer. In the directed variant, enumerating 's outgoing neighbours reads no neighbour entries, but still needs constant work to locate and recognize its empty list. For a multigraph, scanning lists enumerates incident edges with multiplicity; reporting only distinct neighbours additionally requires removing repetitions.
For a short time complexity argument, each reported entry requires at least one output operation, and one scan suffices. Across all vertices, the undirected entry count is by the handshaking lemma; the directed count is . A graph search that processes each vertex once and scans each of its entries once therefore does structural work, provided its visited-state access and FIFO queue or stack operations also have the required constant-time costs. With a full adjacency matrix, scanning every row instead inspects entries. This is how the representation enters the analysis of breadth-first search and depth-first search.
Past exam of the mathematics course of the University of Cambridge 2006 ia Paper 5 5 a iii Solution Created 2026-09-24 Updated 2026-10-14
The two-list functional queue has constant-time
peek and isEmpty, but an individual insertion or removal can cost linear time when it reverses a rear list of length . Its useful guarantee is constant amortized time per operation along a single history starting from empty.For the amortized analysis, each item is consed into the rear once, transferred into the front at most once, and removed at most once. Charge its future reversal to the earlier insertion. Thus operations perform only total list-cell work. More formally, use potential , with sufficient to pay the per-cell reversal cost. An insertion into a nonempty front increases by and has constant actual cost; a reversal of cells decreases by , paying its actual cost. With and ,This amortized analysis is deterministic, not an average over a random workload. It assumes subsequent operations use the successive returned versions. If a persistent old version with a long rear is reused repeatedly, each independent dequeue can redo the same reversal. The simple potential accounting does not give constant amortized cost across such a branching history without further memoization or a stronger persistent FIFO queue implementation.
Past exam of the mathematics course of the University of Cambridge 2006 ia Paper 5 5 a ii Solution Created 2026-09-24 Updated 2026-10-14
Use a two-list functional queue. Its representation Enqueue prepends to the reversed rear list. Removing the head either leaves a nonempty front or reverses the accumulated rear to restore the invariant. The result pair from
(front, rear) denotes the abstract sequence front @ rev rear; the front is nonempty unless the whole FIFO queue is empty. Normalize only when the front runs out:sml
datatype 'a queue = Q of 'a list * 'a list;
exception EmptyQueue;
fun check ([], rear) = Q (rev rear, [])
| check (front, rear) = Q (front, rear);
fun empty () = Q ([], []);
fun isEmpty (Q (front, _)) = null front;
fun enqueue x (Q (front, rear)) = check (front, x :: rear);
fun peek (Q ([], _)) = raise EmptyQueue
| peek (Q (x :: _, _)) = x;
fun dequeue (Q ([], _)) = raise EmptyQueue
| dequeue (Q (x :: front, rear)) = (x, check (front, rear));dequeue contains the removed element and the new FIFO queue. The constructor should be hidden behind an abstract interface so clients cannot construct an unnormalized representation that invalidates isEmpty. Past exam of the mathematics course of the University of Cambridge 2006 ia Paper 5 5 a i Solution Created 2026-09-24 Updated 2026-10-14
A FIFO queue provides an empty queue, an emptiness test, insertion at the rear, inspection of the front item, and removal of the front item. It preserves insertion order: after enqueuing and then , removing an item returns first. Inspection and removal on an empty FIFO queue must have a specified outcome, such as an exception handling case or an option-valued result. In a functional interface, insertion and removal return the new FIFO queue rather than updating their argument.
Ready queue 2026-10-13
A collection of runnable operating-system processes or software threads waiting for a CPU. A running task is not waiting in the ready queue, and a task waiting for input-output is not runnable. FCFS and round-robin scheduling can use a FIFO queue; other policies can organize eligible work differently, for example with a priority queue.
Representation exposure 2026-10-13
Representation exposure gives outside code access that can modify storage on which the representation invariant or promised behavior depends. Returning the internal array exposes a route around the API; merely hiding the field name does not close it. Incoming shared mutable storage can create the same problem. Copies or immutable values can prevent such modification, but their costs and sharing rules belong in the design.[ref]
Reading 13: Abstraction Functions & Rep Invariants. Reading 13, Invariants, Immutability: mutable aliases through both returned values and constructor arguments
The bounded queue with encapsulation deliberately stores immutable labels. A FIFO queue of mutable objects needs a separate promise about whether changing a returned object changes stored content; protecting the queue's ordering and size does not automatically make every stored object immutable.
Round-robin scheduling 2026-10-13
Serve the front of a FIFO queue of runnable tasks for at most one scheduling quantum. If the task finishes or must wait for input-output, it leaves the CPU earlier; if it remains runnable after consuming its allowance, append it to the rear of the ready queue. In the example under process scheduling, the ready queue at time 2 is B, C, A: B arrived at time 1, C joins at the boundary, then A is requeued. That one convention determines the subsequent order.
Stack (data structure) 2026-10-13
A stack is a data structure with last-in, first-out behavior:
push adds an item at the top, pop removes and returns the top item, and peek inspects it without removal. Push : successive removals return . Inspection and removal require a nonempty stack, or a specified empty-case result. A linked list whose head is the top supports all three operations in worst-case time under constant-cost pointer operations and allocation. The stack interface itself does not fix these costs. [ref]https://raw.githubusercontent.com/kevin-wayne/algs4/master/src/main/java/edu/princeton/cs/algs4/Stack.java. Sedgewick and Wayne, Algorithms: Stack interface and implementation
A stack records work that must be resumed in reverse order: the most recent unfinished task is handled first. Depth-first search uses this discipline to finish a newly entered branch before resuming the older branch that led to it. Breadth-first search uses a FIFO queue to resume the oldest pending vertex instead. Both are small interfaces whose removal rule changes the shape of a graph search.

