Binary heap Created 2026-10-13 Updated 2026-10-24
A binary heap represents a priority queue as a complete binary tree obeying a heap order. We use the minimum convention: the priority of every parent in a rooted tree is no greater than the priorities of its children in a rooted tree. Equal priorities are allowed. Each stored entry may be a record carrying a priority key; the numerical example below displays only keys. Reversing the inequalities gives the maximum convention.
The complete binary tree can be stored directly in a zero-indexed array : read its levels from top to bottom, left to right. The root of a tree is at index . The possible children in a rooted tree of index are at and , and an index denotes a present entry only when it is less than . For , its parent in a rooted tree is at , using the floor function. Thus the links of the complete binary tree are determined by arithmetic rather than separately stored pointers.
Consider
The children in a rooted tree of index have keys ; those of index have keys ; those of index have keys . The six comparisons , , , , , establish the heap order. At index , the parent in a rooted tree is index , carrying key .
Figure 1. . Matching indices identify the same entries in both representations. The heap order compares each parent in a rooted tree with its children in a rooted tree; it does not make a sorted array. Details.
The array is visibly not a sorted array: precedes , and precedes . Nor is the last entry a maximum: it is , whereas the maximum is at index . The heap order compares ancestors and descendants, without imposing an order between separate branches. Nevertheless, following the graph path from the root of a tree to any entry gives a chain of nondecreasing priorities. This short argument proves that peek can return , a minimum, without inspecting the other entries.
Insertion appends an entry to the array, preserving the shape of the complete binary tree, then uses sift up to repair the heap order. Insert key into the displayed binary heap. It is appended at index , and exchanges with indices , , then :
The moving key follows ; the keys each move down one level. Only this chain needs repair.
Now apply extract-min. Save key , move the last key to the root of a tree, and shorten the array to length . Use sift down, always choosing the smaller of the present children in a rooted tree:
First exchanges with key at index , since ; then with key at index , since . At index , the possible children in a rooted tree would be indices , both outside the shortened array, so the process stops. The returned key is , and the remaining binary heap is exactly the original one.
Figure 2.
Sift up inserts 1, then sift down restores the original binary heap after removing 1
. The four panels show the start and end of each repair. Colored arrows mark the moving key's graph path. The extraction panels contain seven entries: index 3 has no children in a rooted tree. Details.
For a nonempty binary heap with entries, the deepest level is , using the floor function and logarithm. Each exchange moves one level and uses only a bounded number of comparisons. The resulting time complexity bounds, expressed in Big O notation, are:
OperationTime complexityReason
peekRead the root of a tree.
Insert for Append, then sift up through at most the levels of the complete binary tree.
extract-min for Move the last entry, then sift down through at most those levels.
Build from an arbitrary arrayApply sift down from the last index with children in a rooted tree back to index .
These bounds assume constant-cost indexed access, key comparisons and exchanges, and available array capacity for insertion. Allocating and copying a larger array is a separate cost. Empty and one-entry cases take constant work.
To build a binary heap, begin at index and work backwards. Entries without children in a rooted tree already obey the heap order. Each sift down, also called heapify down, starts with every present smaller rooted tree below it already repaired. Most entries are close to the bottom and can move very little; successively longer repair distances occur for geometrically fewer entries. Summing these distances gives work, rather than charging to every entry. MIT's notes give this bottom-up construction and contrast it with repeated insertion.[ref]
The Dijkstra algorithm additionally needs to decrease the priority of an existing vertex when its tentative distance improves. Given its current index, lowering the key followed by sift up takes time for . An indexed binary heap maintains a separate map from item identity to its current index and updates that map after every exchange. For vertices numbered in a fixed range, the map can be another array, giving constant-time index lookup. An ordinary unindexed binary heap supplies no such guarantee: locating an arbitrary item can require scanning entries. Item identity and priority must remain distinct, especially when several vertices have equal tentative distances.
The attractive compromise is local organization with global usefulness. A binary heap maintains only the heap order, yet every extract-min gives the next smallest key. Repeated extraction of the original example gives , so a priority queue also supplies a sorting algorithm without storing a sorted array between extractions.
Binary search tree Created 2026-10-13 Updated 2026-10-14
A binary search tree stores key-value entries in a binary tree, with distinct keys drawn from a total order. At every vertex, all keys in its left subtree must be smaller than its own key, and all keys in its right subtree must be larger. Thus the entries represent a partial function from keys to values: a key has at most one associated value and may be absent. [ref]
Lookup starts at the root of a tree. Compare the target with the current key: equality returns its value, a smaller target continues into the left subtree, and a larger target continues into the right subtree. Reaching an empty subtree reports absence. The ordering rule justifies discarding the other subtree at every step; this is the algorithm correctness argument for lookup. It applies to the entire subtree, even if that subtree contains many vertices. [ref]
In the seven-key example, search for . At , the comparison selects the right subtree; at , selects the left subtree; at , equality ends the search. The visited keys are , three key comparisons. The right-child chain stores exactly the same keys and satisfies the same binary search tree rule, but lookup of visits , five comparisons. Searching for absent key visits in the first binary search tree and all seven keys in the chain before reaching an empty right subtree.
Figure 1.
Lookup of key in two binary search trees containing the same seven keys
. Orange highlights visited keys and edges; green marks the match. The balanced shape has height of a binary tree and requires three visits, while the chain has height of a binary tree and requires five visits for this target. Details.
For a nonempty binary search tree of height of a binary tree , lookup inspects at most vertices. Under constant-cost key comparisons and child-reference access, its time complexity is in Big O notation, usually written for . With entries, , giving worst-case lookup. If the shape is kept balanced so that , lookup takes for . The empty and one-entry cases take constant work. The worst-case linear bound also appears in Sedgewick and Wayne's ordinary, unbalanced implementation. [ref]
In a shape with every level full, there are vertices, a geometric series. This explains how a small height of a binary tree can accommodate many entries. The binary search tree ordering rule alone does not guarantee this shape or logarithmic time complexity. Breadth-first search also gains no logarithmic key-lookup guarantee merely from having a binary tree: in the displayed balanced example, its left-to-right level order is , so it inspects six keys before finding , and an absent target requires all seven. Directed lookup uses the total order to choose one branch.
The ordering requirement includes every ancestor on the graph path from the root of a tree. Consider the smaller binary tree with root key , left child , right child , and right child under . Key must satisfy both , from its immediate parent in a rooted tree, and , from its position in the root's left subtree. Replacing by preserves all immediate parent-child comparisons, including , but violates . Lookup for would incorrectly go from to and then to an empty left subtree, overlooking the stored key.
Figure 2.
The binary search tree ordering rule constrains an entire subtree
. The valid example has . The invalid example passes immediate parent-child comparisons, but key lies in the left subtree of key and violates its inherited upper bound. Details.
An inorder traversal visits a left subtree, then its own vertex, then a right subtree. On the valid small example its output is ; on the invalid example it is , exposing the descent from to . Both seven-key binary search trees yield . The theorem is that an inorder traversal of a finite binary search tree with distinct keys lists every key once in strictly increasing total order. For a short proof outline, use mathematical induction on the number of vertices: each smaller subtree produces its own sorted list, and the full ordering rule places every left key before the current key and every right key after it. Concatenating these three parts preserves strict order. Sedgewick and Wayne's keys method uses this left-current-right order. [ref]
This combination is useful and attractive: one data structure supports directed lookup and ordered enumeration. An inorder traversal costs time complexity for entries, since it visits every vertex; balance accelerates lookup but cannot eliminate the work of outputting all keys.
// Destination: computer-science.bigb
Binary tree Created 2026-10-13 Updated 2026-10-14
A binary tree, in the data structure convention used here, is a rooted tree in which each vertex has zero, one or two children in a rooted tree, occupying distinct left and right positions. A single left child and a single right child give different binary trees. A vertex with no children in a rooted tree is called a leaf. An empty binary tree has no root of a tree and is also allowed as a storage case. [ref]
For example, give the root of a tree label , its left child label and its right child label . Attach as the left and right children in a rooted tree of , and as those of . This binary tree has seven vertices, six edges, and height of a binary tree : a longest downward graph path contains two edges. The binary search tree lookup illustration below shows this shape alongside the binary tree consisting only of successive right children , whose height of a binary tree is .
Left and right positions specify an ordered shape, not a numerical total order on stored labels. Swapping labels and in the first example still gives a binary tree, but destroys the binary search tree property. Nor must a binary tree be balanced: the right-child chain is just as valid. The same shape convention supports a binary heap, a Huffman code, or a binary search tree, each with its own additional rules. The useful idea is to describe two smaller subtrees at each vertex, making structural recursion natural.
For a precise recursive description, a finite binary tree is either empty or a root of a tree carrying a value together with an ordered pair of disjoint smaller binary trees. The entries of this ordered pair are its left and right subtrees, each of which may be empty. Thus two binary tree child slots exist even when fewer than two children in a rooted tree exist; an empty slot does not denote an extra vertex. This decomposition is the basis of structural recursion.[ref]
Figure 1.
Left and right binary tree child slots distinguish shapes even with just one child
. Solid circles are vertices; outlined squares mark empty binary tree child slots. The first two binary trees differ only in the occupied slot at . The last two have the same four labels but different height of a binary tree. Details.
In the four-vertex mixed example, has left child and right child , while has only a right child . Count its vertices by structural recursion: the empty binary tree contributes zero and each nonempty binary tree contributes one plus the counts of its left and right subtrees. Thus contributes , and contributes . The same decomposition computes height of a binary tree, supports inorder traversal, and supplies short proofs by structural induction. It separates shape from the values stored in a data structure.
Ignoring values, let count finite binary tree shapes with vertices, retaining left and right slots and counting the empty shape once. Splitting at the root of a tree gives the recurrence relation
For each left subtree size , choose its shape and the right subtree shape independently. This yields the Catalan numbers: , , and . The two shapes at are exactly the left-only and right-only examples. Forgetting the slot distinction would change the counting problem.
Bounding volume hierarchy 2026-10-14
A bounding volume hierarchy is a data structure arranged as a rooted tree: leaves store objects, and each internal node stores a bounding volume enclosing its children in a rooted tree. Consequently, every node encloses all objects in its subtree. A common choice is a binary tree of axis-aligned bounding boxes. The objects assigned to sibling subtrees can be different even when their bounding volumes overlap.[ref]
Here is an exact two-dimensional example. Use the triangles from bounding volume, together with having vertices of a polygon and having vertices of a polygon . Group under , and under . Their parent axis-aligned bounding boxes and the box at the root of a tree are
The diagram shows all seven nodes. Taking the coordinate-wise minimum and maximum of the two child boxes constructs each parent box; the resulting box contains the set union of the children, and can also contain empty space between them.
Figure 1.
Four exact triangles, their enclosing boxes, and a seven-node bounding volume hierarchy arranged as a binary tree
. Details.
A bounding volume hierarchy traversal starts at the root of a tree and discards a subtree when its bounding volume misses the query. Accepted internal nodes expose their children; accepted leaves supply candidates for actual shape tests. Box2D's official Collision: Dynamic Tree describes axis-aligned bounding box region queries that return overlapping leaf boxes. A query box that bounds a different query shape can produce additional false candidates.
For the closed query rectangle
left-first depth-first search tests the node boxes in order: root, , , , . The first four overlap ; does not, because its smallest -coordinate is . Pruning skips both and . Five box tests leave two broad phase candidates. The narrow phase rejects , since throughout , and accepts : the point belongs to both and . There are two detailed shape tests and one true hit.
Figure 2.
An exact rectangle query prunes the right subtree and leaves two box candidates but only one triangle hit
. Details.
For a query asking for all intersections, time complexity depends on the number of visited nodes and the cost of each candidate shape test. With fixed dimension and constant bookkeeping cost per node, the work is
where counts candidate objects and is Big O notation. A balanced binary tree has small height of a binary tree, but a query can enter both children at every level. In this example a query containing visits all seven nodes and tests all four triangles. More generally, a full binary tree with single-object leaves has nodes, so such a query takes work for constant-cost shape tests even when its height of a binary tree is . Listing hits itself requires outputs. Small height alone gives no unconditional logarithmic query bound.
For collision detection between two bounding volume hierarchies, traverse pairs of nodes: reject disjoint pairs of bounding volumes, expand a nonleaf member of an accepted pair, and apply the narrow phase at accepted leaf pairs. A single collection's self-query must exclude pairing an object with itself and avoid duplicate unordered pairs. If every object overlaps every other object, reporting all pairs already requires results. Construction quality, empty space in boxes and the queries determine how much pruning is useful.[ref]
For a short correctness outline, an object is enclosed by its leaf box, and each child box is enclosed by its parent box. Repeated subset relations carry this property to every ancestor. A true query intersection therefore prevents rejection at every ancestor of the object's leaf. Updating leaf boxes after motion also requires restoring all affected ancestor bounds before querying.
Breadth-first search Created 2026-09-24 Updated 2026-10-14
Breadth-first search is a graph search that explores successive layers of graph distance from a starting vertex . Here the graph is an undirected graph on a finite set of vertices, and distance counts edges, with no differing edge weights. Mark as discovered, assign , and place it in a FIFO queue. Repeatedly remove the front vertex and scan its adjacency list. Whenever a graph neighbour is still undiscovered, mark it immediately, record as its parent in a rooted tree in the discovery tree, assign , and enqueue at the rear. Marking on insertion ensures that another edge cannot enqueue the same vertex again. [ref]
Use the same undirected graph as depth-first search, with vertex set and edges
where denotes the unordered pair . Start at and scan graph neighbours in lexicographic order of their one-letter labels. The diagram's generator computes the following layers and the parent in a rooted tree assigned to each discovered vertex; the source is the root of a tree and has no parent in a rooted tree.
Graph distance from Vertices in discovery orderParent in a rooted tree in the same order
none
Figure 1.
Breadth-first search: graph distance layers and two ordered FIFO queue snapshots
. Solid edges record first discovery; dashed edges are still present in the original graph. The FIFO queue contains after processing and after processing , with its front on the left. Colors encode graph distance in the graph without edge weights. Details.
The discovery and removal orders both happen to be . After processing , the FIFO queue is : must be processed before the newer . Processing then skips the already discovered and enqueues , giving . Processing adds nothing. Processing discovers , giving ; later sees already marked and leaves its parent in a rooted tree unchanged. The discovery edges are , forming a rooted tree on all seven vertices even though the original graph contains graph cycles. The discovery tree contains six edges; it need not contain every examined edge.
First arrival is shortest because the FIFO queue keeps assigned distances in nondecreasing order, with entries from at most two consecutive layers. While processing distance , newly discovered vertices receive distance and join the rear. If an undiscovered vertex had a shorter graph path, its preceding vertex on that graph path would lie in an earlier layer and would already have discovered it. Thus is the minimum number of edges from to . This is a mathematical induction over the layers, not an assumption about the drawing. Following the parent in a rooted tree backwards at each step gives ; reverse that sequence to obtain the three-edge graph path . is another shortest graph path, but the specified graph neighbour order makes discover first. Changing that order can change the parent in a rooted tree without changing graph distances. [ref]
The shortest-route guarantee concerns the shortest path problem measured by edge count. It also minimizes total cost when every edge has the same positive cost. With unequal edge weights, first discovery need not minimize total cost; nonnegative costs can instead be handled by the Dijkstra algorithm. Breadth-first search is useful for minimum-hop routes and for finding all vertices within a specified graph distance. Its FIFO queue finishes an older layer before the next one, whereas depth-first search uses a call stack or explicit LIFO stack to pursue one branch immediately.
With adjacency lists and constant-cost discovery checks, together with constant worst-case or amortized analysis cost for FIFO queue insertion and removal, the time complexity is in Big O notation. Every reached vertex is enqueued and removed once, each incident edge is scanned at most twice in an undirected graph, and initializing all marks and distances takes . The FIFO queue contains at most vertices; the example's maximum is three. Discovery marks, distances and the recorded parent in a rooted tree for each nonroot vertex also give auxiliary space complexity, excluding the graph. An array that shifts every entry on front removal can lose the linear time complexity; the FIFO queue abstraction alone does not make removal constant-cost. Ordering the adjacency lists is a separate preprocessing cost.
A single start reaches only its connected component of a graph. Unreached vertices retain distance and have no recorded parent in a rooted tree. Restarting at each still-undiscovered vertex, while preserving all discovery marks, produces a forest covering the graph; each new root of a tree gets distance zero, so these distances refer to that root of a tree, not to the original .
Cayley's formula 2026-10-14
For an integer , let be the set of labelled trees with fixed vertex set . Each tree is a finite simple graph, with no distinguished root of a tree, and two trees are different exactly when their sets of edges differ. Then
Equivalently, this is the number of spanning trees of the complete graph . The labelled combinatorial structure includes the fixed labels: drawings, positions, and the order in which edges are listed do not create extra trees. For , the single vertex with no edges is the unique tree; count it separately, since the Prüfer sequence construction requires . For , the unique tree has edge and corresponds to the empty Prüfer sequence. [ref]
For four fixed labels, there are labelled trees, but only two unlabelled trees: the star graph and the path graph. There are four star graphs, one for each choice of centre. There are path graphs: arrange the labels along a graph path, then identify each ordering with its reversal, which describes the same set of edges. Thus . For instance, star graphs centred at and at have different sets of edges even though they have the same shape.
Figure 1.
All sixteen labelled trees on four fixed vertices: four star graphs and twelve path graphs, each with its Prüfer sequence
. Details.
The striking point is that connectedness and the absence of a graph cycle are global restrictions on edges, yet the answer is a power with no correction factor. The Prüfer sequence supplies a bijection that turns those restrictions into freely chosen labels. The rule of product then gives immediately. The same representation makes vertex degrees easy to count and supports uniform labelled tree generation for simulations and algorithm experiments.
Arthur Cayley's 1889 paper "A theorem on trees", published in the Quarterly Journal of Pure and Applied Mathematics, volume 23, pages 376–378, treats the counting problem and its refinement by vertex degrees. It was reprinted as paper 895 in volume XIII of his Collected Mathematical Papers, pages 26–28. This publication is the historical context for the name Cayley's formula; the name alone is not a claim of priority. [ref] [ref]
Complete binary tree Created 2026-10-13 Updated 2026-10-14
A complete binary tree is a binary tree whose levels are full except possibly the deepest, which is filled from left to right with no gaps.[ref]
Here a level groups vertices by their graph distance from the root of a tree. A binary heap uses this shape to maintain logarithmic height of a binary tree. Completeness differs from the two-children condition of a full binary tree.
Figure 1. . Each panel states all three properties. Outlined positions expose gaps in the last level. In particular, the five-vertex example in the lower left is both full and complete but is not perfect. Details.
For a six-vertex example, give two children in a rooted tree , give two children in a rooted tree , and give only a left child . The levels have vertices, and the last occupies its first three positions, so this is a complete binary tree. It is not a full binary tree, since has exactly one child. Moving to the right slot of preserves and height of a binary tree , but leaves a gap before and destroys completeness. Merely keeping the deepest vertices near the left side is insufficient; every earlier position must be occupied.
Number positions by the left-to-right level order of breadth-first search, beginning with root position . The children of position have positions and . A nonempty complete binary tree occupies exactly positions , so its height of a binary tree is : positions form level . This consecutive occupancy explains the compact array representation of a binary heap, while heap order is a separate condition on values. Neither completeness nor the binary tree definition supplies the binary search tree ordering rule.
Decision tree Created 2026-09-24 Updated 2026-10-14
A decision tree represents a deterministic computation of a known Boolean function by inspecting input bits. Each internal vertex of its binary tree names a coordinate to query, its two outgoing edges carry answers 0 and 1, and each leaf carries the output 0 or 1. Starting at the root of a tree, read the named bit, follow its answer edge, and repeat until a leaf is reached. Correctness requires the leaf's label to equal for every input .[ref]
The next coordinate, or the decision to stop, can depend on earlier answers: this is adaptive querying. The same input always follows the same graph path; adaptivity does not require randomness. A correct leaf must have the same output for every completion of the observed bits. Thus a decision tree can stop as soon as the observations form a query certificate. Querying an already known coordinate adds no information, so we use decision trees without repeated coordinates on a graph path; an efficient tree also removes queries made after the output is already forced.
The motivation is exact computation with shortcuts. If inspecting an input entry is expensive, the question is how much of the input must actually be read. The decision-tree query cost counts these inspections, while local calculations on known values are free in this model; this cost need not equal an implementation's time complexity. Here the Boolean function is specified in advance and must be computed exactly on every input. Decision tree learning instead fits a predictor from data, with a different objective.
Depth-first search Created 2026-10-13 Updated 2026-10-20
Depth-first search is a graph search that follows a branch as far as it can before returning to try the next unexplored branch. Starting at a vertex of an undirected graph on a finite set of vertices, mark as discovered. Scan its graph neighbours in a fixed order: for each undiscovered vertex, record the current vertex as its parent in a rooted tree in the discovery tree, mark the new vertex, and explore it immediately using recursion. Return when its adjacency list is exhausted. Discovery marks persist after return, preventing a graph cycle from causing repeated exploration. This branch-and-return rule is the maze exploration described in MIT's notes. [ref]
Use the same unweighted undirected graph as breadth-first search, with vertex set and edges
where denotes the unordered pair . Visit graph neighbours in lexicographic order of their one-letter labels, starting at . The discovery order, computed by the diagram's generator, is
The discovery edges in order are . They form a rooted tree spanning the reached vertices, with root of a tree . The other edges, and , remain in the original graph but never discover a new vertex. In particular, the graph cycle causes no repeated discovery.
Figure 1.
Depth-first search: discovery edges and the active call stack on seven vertices
. Numbers show first-discovery order. Solid edges form the discovery tree; dashed edges belong only to the original graph. The right panel shows the call stack from oldest call to current call, including the return from before entering . Details.
At there is no undiscovered graph neighbour, so its call returns to . The next call enters , then , then , then . Immediately after discovering , the call stack is , with on top; is still discovered but its call has finished. The maximum call stack depth is six, although seven vertices are discovered. Following the recorded parent in a rooted tree backwards at each step reconstructs a graph path; here the route from to is , using five edges. Breadth-first search instead finds , using three edges. Depth-first search establishes reachability but does not guarantee the fewest edges.
An explicit LIFO stack can replace recursion, but its entries and discovery rule must be specified. To reproduce this exact traversal, store one frame per active vertex, retaining the next position in its adjacency list. Advance the top frame by one graph neighbour; if that vertex is undiscovered, mark it and push its frame immediately; pop an exhausted frame. Pushing all undiscovered graph neighbours at once and marking them on push is a different iterative variant. Even pushing them in reverse lexicographic order does not generally reproduce the parent in a rooted tree relationships above: would already be marked while processing , so could not discover .
With an adjacency list representation, constant-cost discovery checks and frame operations, and the graph neighbours already ordered, depth-first search has time complexity in Big O notation. Each reached vertex is entered once and each incident edge is examined at most twice in an undirected graph; initializing all discovery marks costs . The call stack has depth at most , since no active vertex repeats. Discovery marks and the recorded parent in a rooted tree for each nonroot vertex also need auxiliary space complexity, excluding storage for the graph. Sorting adjacency lists to obtain a chosen order is additional work. [ref]
One start explores only its connected component of a graph. To cover a disconnected graph, start again at every still-undiscovered vertex while keeping all discovery marks; the discovery trees form a forest. Depth-first search is useful for reachability, constructing a spanning tree of a connected graph, and organizing the return steps needed by a depth-first traversal of a tree. For detecting a graph cycle in a simple graph that is an undirected graph, an edge to an already discovered vertex other than the current parent in a rooted tree closes a graph cycle; the immediate return edge to that parent in a rooted tree is not itself a graph cycle.
// Target: computer-science.bigb
DFS lowpoint 2026-10-14
For a finite simple graph that is an undirected graph, the DFS lowpoint of is the smallest DFS discovery time reachable by following zero or more discovery edges down its rooted tree, then at most one non-discovery edge to an ancestor. Staying at is allowed. Ignore the reverse traversal of the discovery edge to the parent in a rooted tree: it is the same edge, not an escape route. Start with . On returning from a child in a rooted tree , replace by . For a non-discovery edge from to an earlier ancestor , replace it by . This summarizes how far upward the explored branch can reconnect. [ref]
The cut vertex criterion has a separate case for each root of a tree in the discovery forest:
Why does equality matter? If , the branch below can reconnect to , so the discovery edge lies on a graph cycle and is not a bridge in a graph. Deleting the vertex destroys that reconnection too. If has a parent in a rooted tree, the branch is then separated from that parent in a rooted tree, explaining the non-strict cut vertex test. For a root of a tree, there is no earlier side to separate from; distinct discovery branches cannot have an edge between them, since depth-first search would have explored them as one branch. This gives the two-children in a rooted tree rule. These are proof outlines of the criteria. [ref][ref]
In the joined- example with DFS discovery times , the DFS lowpoints in label order are . For and its child in a rooted tree , : is a bridge in a graph, and is a cut vertex. For and its child in a rooted tree , : is a cut vertex, although is not a bridge in a graph. The root of a tree has only one child in a rooted tree, , so it is not a cut vertex. In the shared- example, the root of a tree has two children in a rooted tree, and , and is a cut vertex, while every DFS lowpoint is and no edge passes the strict bridge in a graph test.
Restart depth-first search at every undiscovered vertex to cover a disconnected graph, applying the root of a tree rule separately in each connected component of a graph. With adjacency lists and constant-cost label operations, computing all DFS lowpoints, cut vertices and bridges in a graph has time complexity in Big O notation, because each vertex is discovered once and each edge is inspected twice. The simple parent-skipping rule assumes a simple graph. In a multigraph, skip only the actual parent edge, identified individually: a parallel edge to the same parent in a rooted tree is a valid reconnection and can prevent the first edge from being a bridge in a graph. The criteria here concern undirected graphs; a directed graph requires a different connectivity analysis.
Disjoint-set forest 2026-10-18
A disjoint-set forest represents each block of a set partition by a rooted tree. Each set element stores a pointer to its parent in a rooted tree; the root of a tree stores a pointer to itself as a stopping convention. These self-pointers are sentinels, omitted from the forest's edges. Following parent pointers reaches the disjoint-set representative, the root of a tree. An indexed array parent suffices when members are numbered consecutively. The rooted trees encode membership; their edges need not be edges of any input graph.
To link different blocks of a set partition, point one root of a tree at the other root of a tree. Linking roots preserves every old membership and joins exactly the two rooted trees. Arbitrarily reparenting a nonroot could detach only part of a block of a set partition, so it would not implement the required disjoint-set union operation. The disjoint-set find operation terminates because each nonroot pointer moves towards the unique root of a tree; linking distinct roots cannot introduce a graph cycle.
Exponential generating function Created 2026-10-07 Updated 2026-10-20
An exponential generating function encodes a sequence using . For labelled counting, is the number of structures on a fixed set of distinct labels. Labels distinguish otherwise similar objects: changing which person belongs to a group can change the structure. Recover the count by coefficient extraction as . The raw coefficient is , not .
The factorial makes multiplication account automatically for distributing labels. To combine an -structure on labels and a -structure on the remaining , choose the first label subset in ways, then choose the two structures. The binomial coefficient counts how the two groups of labels interleave within the full label set. Thus
The normalization works because . This explains the usefulness of exponential generating functions for labelled counting: an ordinary Cauchy product would omit the choices of labels. See Peter Magyar, Math 482, notes for 2/7, labelled product principle.
For a concrete example, there is one undecorated set on any given collection of labels. Its exponential generating function is the exponential function . Combine a red set and a blue set, allowing either to be empty:
Every label independently receives one of two colours, giving assignments by the rule of product. With three labels, the counts by number of red labels are , totalling eight. Choosing only the two group sizes would give the four possibilities ; it would forget which labels are red.
Indeed, the ordinary generating function for the constant sequence is the geometric series . Its square has coefficient , counting pairs of nonnegative sizes. Both encodings are correct for their respective questions. The decision is whether identity matters when objects are combined.
For unordered sets of labelled components of positive size, an exponential generating function becomes : the term forgets the ordering of components. The existing rooted-tree generating function develops the richer example . A labelled rooted tree consists of its root of a tree and an unordered set of smaller labelled rooted trees, connecting the same label-distribution mechanism to recursive counting.
Full binary tree Created 2026-10-13 Updated 2026-10-14
A full binary tree is a binary tree in which every nonleaf has exactly two children in a rooted tree; equivalently, no vertex has just one child.[ref]
A binary Huffman code with at least two positive-probability symbols has a full code tree: a vertex with only one child could be suppressed to shorten all codewords below it.
Let have children in a rooted tree , and let have children in a rooted tree , with leaves. Every vertex has zero or two children in a rooted tree, so this five-vertex binary tree is full. It is not a complete binary tree: level has empty positions under before the occupied positions under . Instead put under and leave a leaf. The resulting five-vertex binary tree is both full and complete, yet is not a perfect binary tree because its leaves occur at two different distances from the root of a tree.
If a nonempty finite full binary tree has nonleaf vertices and leaves, then its edges can be counted as , two leaving each nonleaf, or as , using the tree count. Hence
Thus is odd, but odd size alone does not imply fullness: a three-vertex chain is a counterexample. Nor does fullness guarantee small height of a binary tree. Repeatedly give one continuing vertex a leaf in one slot and another continuing vertex in the other, ending with two leaves. With nonleaf vertices, this constructs a full binary tree of vertices and height of a binary tree . The two-children rule permits height growing linearly with size.
Height of a binary tree Created 2026-10-13 Updated 2026-10-14
For a nonempty binary tree, the largest number of edges on a downward graph path from its root of a tree to a leaf. A single vertex has height of a binary tree ; a chain of vertices has height of a binary tree . A convenient recursion convention assigns an empty binary tree height , giving for the left and right subtrees. A binary search tree lookup visits at most vertices.
The convention counts edges, rather than vertices on the longest graph path. Its recursive form is
[ref]
For a leaf, both subtrees are empty, giving . For the mixed four-vertex example, , , and . The four-vertex chain has height of a binary tree . A convention that counts vertices would add one to every nonempty binary tree height, so a height formula must specify its convention.
At distance from the root of a tree, there are at most vertices: each vertex in the preceding level has at most two children in a rooted tree. Summing this geometric series and using the longest graph path gives, for ,
The upper bound is attained by a chain; a perfect binary tree attains the capacity bound. For , the minimum possible height of a binary tree is , as in the mixed example, while the maximum is . The binary tree definition permits both extremes. Small height of a binary tree bounds the length of a directed lookup in a binary search tree; evaluating the height of a binary tree by the displayed structural recursion still examines all vertices, requiring time complexity under constant-cost child access and arithmetic.
Huffman code Created 2026-10-14 Updated 2026-10-25
A Huffman code is the prefix code returned by Huffman coding; the algorithm chooses a code tree, while the code specifies the actual symbol-to-codeword assignment. For the probability distribution in symbol order , the illustrated binary tree gives
The codeword lengths are . This is a prefix code because no complete codeword is an initial segment of another complete codeword. Thus a decoder can start at the root of a tree, follow one edge per bit, emit a symbol on reaching its leaf, then restart at the root of a tree. In particular, 011010111 splits as 0 | 110 | 10 | 111 and decodes to . No separators are transmitted: the leaf tells the decoder where a codeword ends.
The expected codeword length is
bits per source symbol. Four symbols would require bits each if all codewords had the same length, so this Huffman code saves bit per symbol on average, or of that fixed-length payload. A particular message can grow: uses nine bits here instead of eight. These lengths count the encoded symbols only; transmitting a code description or message framing can add further cost.
The Kraft inequality is saturated by this Huffman code:
Its Shannon entropy is
bits per symbol, slightly below the expected codeword length . The entropy lower bound for prefix codes applies to every binary prefix code for this probability distribution. It need not be attainable with integer codeword lengths for individual symbols; Huffman coding reaches the best mean within that class. [ref]
A Huffman code need not be unique. In the first example, the tied and weights can exchange their edge labels, changing codewords but preserving their codeword lengths. Ties can also change the lengths themselves. For a second probability distribution , first merge to weight . The next merge can join with either or the subtree, since both have weight . Joining with permits , with all lengths . Joining with the subtree permits , with lengths . Both are optimal prefix codes with expected codeword length : for the latter, . Tie choices can change the code tree without changing the minimum mean.
// Target: algebra.bigb
Huffman coding Created 2026-09-24 Updated 2026-10-14
Huffman coding makes frequent symbols cheap to store by giving them short codewords, while allowing rare symbols longer codewords. For a known probability distribution on a finite alphabet with at least two positive-probability symbols, binary Huffman coding constructs a prefix code minimizing expected codeword length among binary prefix codes that encode one source symbol at a time. The objective is an average under that probability distribution; it does not promise to shorten every message. Encoder and decoder must agree on the resulting Huffman code. [ref]
The construction grows a binary tree from its leaves towards its root of a tree. Start with one leaf per symbol, weighted by its probability. Repeatedly join the two currently smallest weights beneath a new parent in a rooted tree, whose weight is their sum, and replace the pair by that subtree. Include newly formed subtrees when choosing the next pair. When one tree remains, label the two outgoing edges at every internal vertex with and ; the labels on the graph path from the root of a tree to a symbol give its codeword. This is a greedy algorithm: each step makes a locally cheapest merge, yet the result is an optimal prefix code.
For a concrete example, use probabilities , , , . First join and , creating weight . The remaining weights are for , for the subtree, and for . Join the two weights to make , then join with that subtree to make . The merge weights are therefore . Each merge adds one bit to every codeword below it, so their sum is the expected codeword length: bits per source symbol. The diagram fixes the edge labels to produce the Huffman code used below.
Figure 1.
Huffman merges for probabilities 0.4, 0.3, 0.2, 0.1 and their binary codewords
. Details.
The useful insight is that choosing short codewords is a resource allocation problem: the prefix code condition constrains the available codeword lengths through the Kraft inequality. Huffman coding solves this one-symbol problem exactly for the supplied probability distribution. For repeated emissions of a memoryless classical information source, the same Huffman code can be applied symbol by symbol. More general compression can exploit dependencies or encode groups of symbols; the one-symbol optimality statement does not compare all such methods.
Leaf depth in a code tree Created 2026-10-14 Updated 2026-10-31
The number of edges on the graph path from the root of a tree to the leaf for symbol in a code tree. The root of a tree has depth zero. Each edge contributes one bit to a binary codeword, so this depth equals the codeword length; weighting these depths by probabilities gives expected codeword length.
Optimal prefix code Created 2026-09-24 Updated 2026-10-14
An optimal prefix code minimizes expected codeword length for a fixed source probability distribution. Here the source alphabet is finite, has symbols, and has for every symbol; each source symbol receives one codeword over the binary output alphabet . Its code tree puts the symbols at leaves. Reading the edges along the graph path from the root of a tree to a leaf produces its codeword, so the leaf depth in a code tree is exactly its codeword length. Thus
For unnormalized positive weights, minimize instead; the corresponding expected codeword length is . This connects the abstract optimization to storage or transmission: counts the bits charged when symbol occurs. Huffman coding attains this minimum; the Huffman sibling property and Huffman sibling contraction explain why. [ref]
For , a balanced code tree charges every symbol two bits, giving . The codeword lengths charge the most frequent symbol only one bit, giving . The choice concerns weighted cost, not just the greatest codeword length: increasing that maximum from two to three can improve the average.
The search over prefix codes looks infinite, but positivity reduces it to finitely many full binary trees with leaves. A vertex with one child can be suppressed to improve cost, and a full binary tree with leaves has internal vertices. There are consequently finitely many such shapes and symbol assignments, so the minimum exists. For four leaves, the only possible sorted codeword lengths in a full binary tree are and . Probability monotonicity of optimal prefix-code lengths assigns larger probabilities to shallower leaves, giving respective minimum costs and in this example. This is an independent small-instance check of the Huffman code.
These hypotheses matter. With zero weights, suppressing a subtree carrying only zero weight need not strictly improve cost, so an optimal prefix code need not have a full binary tree. A one-symbol source raises the convention of whether an empty codeword is allowed. Both cases are outside the original statement here. Encoding groups of symbols changes the source alphabet and the optimization problem; the minimum here concerns one source symbol per codeword.
Parent in a rooted tree Created 2026-10-14 Updated 2026-10-25
For a nonroot vertex, its adjacent predecessor on the unique graph path from the root of a tree. The root of a tree has no parent.
A binary search tree is a binary tree storing distinct keys from a total order, with every key in a node's left subtree smaller than that node's key and every key in its right subtree larger. The condition concerns entire subtrees, not just immediate neighbours.
For membership, start at the root of a tree and compare the target with the current key. Return true on equality; continue into the left subtree for a smaller target and the right subtree for a larger target; return false on an empty subtree. The binary search tree ordering ensures that a discarded subtree cannot contain the target. Each step descends one level, so the algorithm terminates and uses time complexity for height of a binary tree , under constant-time key comparison.