Algorithm Search⌘K

Proofs: Disjoint-set forest

These are the human proofs of Disjoint-set forest, at full length.

The operations of a disjoint-set forest keep the forest and rank invariants and implement the disjoint-set type full

This proof shows: correctness, termination.

We write EE for the set of elements made so far, and T(r)T(r) for the set of nodes whose path of parent pointers ends at the root rr. The sets of the structure are the sets T(r)T(r) over all roots rr. We prove that the two invariants of the page hold after each operation:

(F) For each x∈Ex \in E, the sequence x,x.p,x.p.p,…x, x.p, x.p.p, \ldots reaches a root, an element rr with r.p=rr.p = r, after at most ∣E∣|E| steps.

(R) For each non-root xx, x.rank<x.p.rankx.rank < x.p.rank. Each root rr has ∣T(r)∣≥2r.rank|T(r)| \ge 2^{r.rank}.

Under (F), the sets T(r)T(r) are pairwise disjoint and cover EE, because each element reaches exactly one root. So the structure represents a collection of disjoint sets, each with its root as representative.

Lemma 1 (FIND). Assume (F) and (R). Then FIND(x)(x) stops, returns the root rr of xx, and after it (F) and (R) hold, each set T(⋅)T(\cdot) is the same as before, and no rank has changed.

Proof. Let x=x0,x1,…,xk=rx = x_0, x_1, \ldots, x_k = r be the path from xx to its root, with xi+1=xi.px_{i+1} = x_i.p and k≥0k \ge 0. By (R), x0.rank<x1.rank<⋯<xk.rankx_0.rank < x_1.rank < \cdots < x_k.rank.

Termination and result. By induction on kk. If k=0k = 0, then x.p=xx.p = x, line L3 fails, and line L5 returns x=rx = r. If k≥1k \ge 1, line L4 calls FIND(x1)(x_1), whose path x1,…,xkx_1, \ldots, x_k is shorter. By the induction hypothesis it stops and returns rr, and its only changes are to set xi.p←rx_i.p \leftarrow r for 1≤i<k1 \le i < k. Line L4 sets x0.p←rx_0.p \leftarrow r, and line L5 returns rr.

Invariants. So the only changes of the whole call are xi.p←rx_i.p \leftarrow r for 0≤i<k0 \le i < k, made in the order i=k−1,…,0i = k - 1, \ldots, 0. Take one such change. Before it, xix_i reaches rr; after it, xix_i reaches rr in one step. Each other node yy whose path passes through xix_i reached rr through xix_i before, and still reaches rr through xix_i after, by a path that is not longer. No other path changes. So (F) holds and each T(⋅)T(\cdot) keeps its members. For (R): xi.rank<xi+1.rank≤r.rankx_i.rank < x_{i+1}.rank \le r.rank, by the chain of ranks above, so xi.rank<r.rankx_i.rank < r.rank after the change. No rank changes, so the root part of (R) is untouched, and the sets T(r)T(r) do not change, so their sizes do not change. □\square

Lemma 2 (MAKE-SET). If (F) and (R) hold and x∉Ex \notin E, then after MAKE-SET(x)(x) they hold for E∪{x}E \cup \{x\}, and the sets are the old sets and {x}\{x\}, with representative xx.

Proof. Lines L1 and L2 make xx a root of rank 0 with T(x)={x}T(x) = \{x\}, and ∣T(x)∣=1=20|T(x)| = 1 = 2^0. No other field changes, so each other path and each other set is as before. □\square

Lemma 3 (UNION). Assume (F) and (R), and let x,y∈Ex, y \in E with sets A=T(FIND(x))A = T(\mathrm{FIND}(x)) and B=T(FIND(y))B = T(\mathrm{FIND}(y)). After UNION(x,y)(x, y), (F) and (R) hold. If A=BA = B, the sets are unchanged. Else the sets are the old sets with AA and BB replaced by A∪BA \cup B, and the representative of each other set is unchanged.

Proof. By Lemma 1, line L6 sets xx and yy to the roots of AA and BB, and keeps the invariants and the sets. If x=yx = y, line L7 returns, and A=BA = B. Else x≠yx \ne y are two roots, so A∩B=∅A \cap B = \emptyset. Write a=x.ranka = x.rank and b=y.rankb = y.rank.

Case a>ba > b (line L8). The only change is y.p←xy.p \leftarrow x. Each node of BB now reaches yy and then xx, and each node of AA reaches xx as before, so T(x)=A∪BT(x) = A \cup B and the other sets do not change. A path in A∪BA \cup B is at most ∣A∣+∣B∣|A| + |B| nodes long, so (F) holds. For (R), the new non-root yy has y.rank=b<a=x.ranky.rank = b < a = x.rank. The root xx has ∣T(x)∣=∣A∣+∣B∣>∣A∣≥2a|T(x)| = |A| + |B| > |A| \ge 2^{a}, and its rank is still aa.

Case a≤ba \le b (lines L9 and L10). The change x.p←yx.p \leftarrow y makes T(y)=A∪BT(y) = A \cup B, and (F) holds as in the first case. If a<ba < b, the new non-root xx has x.rank=a<bx.rank = a < b, and ∣T(y)∣>∣B∣≥2b|T(y)| > |B| \ge 2^b. If a=ba = b, line L10 sets y.rank=b+1y.rank = b + 1. Then x.rank=b<b+1x.rank = b < b + 1, so the edge from xx is fine. Each other child zz of yy had z.rank<bz.rank < b, which is still less than b+1b + 1. And ∣T(y)∣=∣A∣+∣B∣≥2a+2b=2b+1|T(y)| = |A| + |B| \ge 2^a + 2^b = 2^{b+1}, by (R) for the two old roots.

In all cases only xx or yy stopped being a root, and the representative of each set other than AA and BB is its old root. □\square

Theorem. Starting from the empty structure, after any sequence of MAKE-SET, FIND and UNION operations with valid arguments, (F) and (R) hold, each operation stops, and the sets T(r)T(r) with representatives rr are exactly the sets of the disjoint-set type after the same sequence. In particular, FIND$(x) = $ FIND(y)(y) if and only if xx and yy are in the same set, which is law (D3).

Proof. The empty structure has no elements, so (F) and (R) hold. By induction on the number of operations, using Lemma 2 for MAKE-SET, Lemma 1 for FIND and Lemma 3 for UNION, the invariants hold after each operation, and each operation changes the represented sets exactly as the type says. FIND returns the root of the tree of xx, which is the representative of its set. Two elements have the same root exactly when they are in the same tree, by (F). ■\blacksquare

Corollary (height). Under (R), each tree has height at most ⌊lg⁡∣E∣⌋\lfloor \lg |E| \rfloor.

Proof. On a path x0,…,xkx_0, \ldots, x_k to a root rr, the ranks strictly increase from x0.rank≥0x_0.rank \ge 0, so k≤r.rankk \le r.rank. By (R), 2r.rank≤∣T(r)∣≤∣E∣2^{r.rank} \le |T(r)| \le |E|, so r.rank≤lg⁡∣E∣r.rank \le \lg |E|, and kk is an integer. □\square

Back to Disjoint-set forest