Past exam of the computer science course of the University of Oxford 2018 Algorithms 1 b Solution 2026-10-31
First perform splaying on the key to be deleted, making its node the root of a tree. Delete that root, leaving left and right subtrees . If either is empty, return the other. Otherwise find the maximum key of by following right-child references, and perform splaying on within . This makes the root of with an empty right subtree. Attach there. The result is the original splay tree with exactly the selected key removed. An unsuccessful lookup leaves the represented set unchanged.
For algorithm correctness, all keys of are smaller than the deleted key, and all keys of are larger. Splaying preserves the binary search tree property by the permitted assumption. Since is the maximum of , it has no larger key within ; since every key of exceeds , attaching as its right subtree preserves every ordering condition. All remaining keys occur once. This is the join-based deletion of a splay tree.[ref]
Self-Adjusting Binary Search Trees by Daniel Sleator and Robert Tarjan. Author-hosted publication record and abstract: splay-tree search, insertion and deletion operations
Take a root with children . Give the children , give the children , and give the children . The root of a tree has degree two, the three vertices have degree three, and are the five leaves of a graph. There are nine vertices and eight edges, as required by the handshaking lemma and the edge count for a tree.
Store a complete binary tree in a one-indexed array , level by level. Index has parent in a rooted tree for and possible children in a rooted tree and , present only when their indices are at most . The max-heap condition is for every .
Following these inequalities from the root of a tree to any entry proves that is a maximum. The heap order does not sort siblings or unrelated branches. The complete binary tree has height , which bounds how far any single repair can travel. Store the current heap size separately from the array's capacity.
Path compression 2026-10-18
Path compression changes parent pointers during a disjoint-set find operation so that future queries traverse fewer edges. Full path compression first follows the entire parent route to its root of a tree, then makes every member on that route point directly to that same root of a tree. No member changes its block of a set partition or its disjoint-set representative. Pointers outside the traversed route stay as they were. The following iterative Python implements full path compression and union by rank;
parent and rank are initially indexed arrays with parent[x] = x and rank[x] = 0 for every valid member.def find(x):
root = x
while parent[root] != root:
root = parent[root]
while parent[x] != x:
following = parent[x]
parent[x] = root
x = following
return root
def unite(x, y):
a, b = find(x), find(y)
if a == b:
return False
if rank[a] < rank[b]:
a, b = b, a
parent[b] = a
if rank[a] == rank[b]:
rank[a] += 1
return TrueStarting from the displayed disjoint-set forest,
find(3) traverses , returns and changes only from to . The route still has two edges. Then find(5) changes only from to . The final parent array is ; every stored rank retains its displayed value. The rooted tree at now has height one although its root's rank is two. Root still represents a separate singleton set.find(3) followed by find(5). Labels record stored ranks, including historical ranks at nonroots. Details.The two-pass algorithm first discovers the answer and then reuses it. During the second pass, saving
following before overwriting the pointer preserves the remaining route. Every replacement pointer targets the original root of a tree, proving that the partition of a set is unchanged.Full path compression is one specific rule. The authored
UF.java implementation instead uses path halving, redirecting a visited member to its parent's parent while advancing along the route. Its union by rank rule agrees with the one above.[ref]UF.java. Algorithms, 4th edition by Robert Sedgewick and others; UF.java, find and union methods: halving assignment versus the full-compression algorithm here; lower-rank linking and equal-rank increment
Perfect binary tree 2026-10-14
A nonempty binary tree in which every level, including the deepest, contains all its possible vertices. Equivalently, it is a full binary tree whose leaves are all at the same graph distance from the root of a tree.[ref]
9.1 Binary trees. Data Structures and Algorithms, section 9.1.1: perfect shape, equal leaf levels, and Figure 9.4
Every perfect binary tree is both a full binary tree and a complete binary tree; the five-vertex example above shows that the converse fails even when both properties hold. These definitions fix the terminology used here.
For height of a binary tree , the level sizes are , giving by a geometric series. There are leaves. The seven-vertex example has level sizes and height of a binary tree ; the single-vertex binary tree is already perfect, with . More generally, joining two perfect binary trees of equal height of a binary tree under a fresh root of a tree gives the next such shape. Equal heights are essential: fullness alone allows unequal leaf distances. A perfect binary tree realizes the maximum number of vertices for its height of a binary tree, making the exponential capacity behind short lookup graph paths visible.
// Target: probability-and-statistics.bigb
Rooted tree Created 2026-09-28 Updated 2026-10-14
A rooted tree is a tree with a distinguished vertex, its root of a tree . Choosing turns connections into a hierarchy: every other vertex has a unique parent in a rooted tree, the preceding vertex on its graph path from . Conversely, the vertices whose parent in a rooted tree is are the children in a rooted tree of . Choosing the root of a tree changes this description, while the underlying edges remain the same. Arrows towards the root of a tree can encode the relationship, as in MIT's counting notes; the undirected tree itself needs no arrows. [ref]
In the seven-vertex tree above, choose . The levels, grouped by graph distance from the root of a tree, are , , , . The children in a rooted tree of are , and the parent in a rooted tree of is . Choosing instead makes the levels , , , , , : now has parent in a rooted tree , reversing their relationship. All six edges survive.
This hierarchy supports structural recursion: process the smaller rooted trees below each vertex, then combine their results. A depth-first traversal of a tree explores one branch before returning; breadth-first search processes successive levels. The lowest common ancestor identifies where two routes from the root of a tree last coincide. For it is when . A binary tree imposes an additional restriction on children in a rooted tree; a general rooted tree has no such bound.
Sift up 2026-10-13
After inserting or lowering a key in a minimum-oriented binary heap, compare it with its parent in a rooted tree. Exchange them while the moving key is smaller, then continue at its new index. Stop at the root of a tree or when the heap order is satisfied. This repair assumes the rest of the binary heap was valid before the insertion or key decrease.
Subtree Created 2026-10-13 Updated 2026-10-14
For a vertex in a rooted tree, its subtree contains and every vertex reachable by repeatedly following children in a rooted tree, together with the connecting edges; its root of a tree is . In a binary tree, the left subtree is rooted at the left child, and is empty when that child is absent; the right subtree is defined similarly. A binary search tree constrains every key in these subtrees.
Union by rank 2026-10-18
Union by rank keeps a nonnegative integer rank, initially zero, for each member. For each input, obtain its root of a tree using the disjoint-set find operation, then compare the resulting ranks. Attach the lower-rank root of a tree below the higher-rank root of a tree, leaving both ranks unchanged. When the two disjoint-set representatives differ but their ranks are equal, choose either survivor and increase its rank by exactly one. A redundant disjoint-set union operation changes no ranks. Path compression also changes no ranks. The surviving root's rank bounds the height of its rooted tree, measured in edges; after path compression it need not equal that height.[ref]
COS 226 Bob’s Notes 1: Union-Find and Percolation (Version 2) by Robert Tarjan. Robert Tarjan, COS 226 Bob’s Notes 1: Union-Find and Percolation, Version 2, Fall 2010, p. 4: rank linking, equal-rank increment and upper-bound interpretation after compression
In our example, let the first argument's root of a tree survive equal-rank ties. The first two merges create roots , each of rank . The third gives and increases the rank of to . The fourth creates root of rank . The fifth attaches below without increasing any rank. Before any subsequent compression queries, the indexed arrays areThe redundant call on leaves these arrays unchanged. In particular, the disjoint-set representative of is , although is the minimum member of its block of a set partition.
Two short arguments explain the rank invariant. First, a root of rank has at least members in its block of a set partition: rank zero starts with one, and increasing rank combines two disjoint blocks of a set partition with at least members each. Unequal-rank linking only adds members. Thus every rank is at most for stored members, using the floor function and logarithm. Second, height is initially zero; unequal-rank linking adds at most one to the lower height, while equal-rank linking raises the available bound by one. Path compression only shortens routes. These arguments prove a height bound, not the stronger amortized analysis below.

