Algorithm Search⌘K

Proofs: Burst trie

These are the human proofs of Burst trie, at full length.

The burst trie operations keep the invariant and implement the symbol table full

This proof shows: correctness.

We use the representation, the invariant (B1) to (B3) and the pseudocode of the page. The place of a key ss in the current structure is defined by the walk: start at the root with d=0d = 0; while at an access node xx with d<∣s∣d < \lvert s \rvert whose slot for s[d]s[d] holds an access node, move to it and add 1 to dd. The walk stops at an access node xx with either d=∣s∣d = \lvert s \rvert (the place is x.valx.val) or with the slot for s[d]s[d] holding a container cc or empty (the place is the pair with string s[d+1..]s[d+1 ..] in cc, or the empty slot). By construction path(x)=s[0..d−1]path(x) = s[0 .. d-1].

Lemma 1 (unique place). Under (B1), if ss is stored, it is stored at its place.

Proof. By (B1), ss is stored either as path(y)path(y) for an access node yy, or as path(c)⋅tpath(c) \cdot t for a container cc. In the first case, path(y)=spath(y) = s, so yy lies on the walk of ss (each ancestor of yy is an access node whose path is a prefix of ss, and its slot for the next symbol of ss leads towards yy), and the walk reaches yy with d=∣s∣d = \lvert s \rvert. In the second case, path(c)path(c) is a prefix of ss, of length ∣path(c)∣=e\lvert path(c) \rvert = e, and cc hangs in the slot for s[e−1]s[e - 1] of an access node xx with path(x)=s[0..e−2]path(x) = s[0 .. e-2]. The walk reaches xx (same argument) with d=e−1<∣s∣d = e - 1 < \lvert s \rvert and stops there, because the slot holds a container. Its place is the pair with string s[e..]=ts[e ..] = t in cc. □\square

GET. Lines L1 to L3 perform the walk of the definition. If the walk ends with d=∣s∣d = \lvert s \rvert, line L2 returns x.valx.val; else line L4 looks up s[d+1..]s[d+1 ..] in the container, correctly by (B3) for a binary search, and line L5 returns its value or NIL. By Lemma 1 and (B1), this is the value of ss or NIL.

PUT. Line L6 performs the walk. If it ends at an access node with d=∣s∣d = \lvert s \rvert, setting x.valx.val stores ss at its place. Otherwise, lines L7 to L9 put (s[d+1..],v)(s[d+1 ..], v) in the container of the slot for s[d]s[d], keeping it sorted and without repeats, so by Lemma 1 the key ss is stored once, with value vv, and the other keys are untouched. Now (B1) and (B3) hold, and (B2) can fail only at that container, if it has L+1L + 1 pairs.

BURST. Let cc hang at path qq and be replaced by the access node yy, so path(y)=qpath(y) = q. Each pair (t,v)(t, v) of cc stood for the key q⋅tq \cdot t. Line L11 stores it as y.valy.val if t=εt = \varepsilon, which stands for path(y)=qpath(y) = q; else as the pair (t[1..],v)(t[1 ..], v) in the container at path q⋅t[0]q \cdot t[0], which stands for q⋅t[0]⋅t[1..]=q⋅tq \cdot t[0] \cdot t[1 ..] = q \cdot t. So the set of stored keys and their values does not change, and (B1) holds. The strings of cc are distinct, so at most one has t=εt = \varepsilon and the new containers have no repeats; appending in the sorted order of cc keeps each new container sorted, since strings with the same first symbol are ordered by their remainders. So (B3) holds. Line L12 bursts each new container with more than LL pairs, by the same argument. Each burst at depth ee moves the pairs one symbol deeper, and the strings are finite, so the bursting ends; at the end every container has between 1 and LL pairs, and (B2) holds.

DELETE. The walk finds the place of ss (Lemma 1). Removing the pair or clearing x.valx.val removes exactly the key ss; a container that becomes empty is removed from its slot, so (B2) keeps its lower bound of 1.

Prefix queries and order. The keys with prefix pp are those stored below the place where the walk of pp stops. If it stops in a container cc at path p[0..d]p[0 .. d], they are the pairs of cc whose string starts with p[d+1..]p[d+1 ..], which form a contiguous run in sorted order (B3). If it stops at an access node xx with path(x)=ppath(x) = p, they are all keys below xx. A walk that reports y.valy.val before the children of yy, takes the slots in increasing order of their symbols, and reports each container in its sorted order, lists keys in lexicographic order: a key path(y)path(y) is a prefix of every other key below yy, and keys in different slots of yy first differ at the symbol of the slot. ■\blacksquare

Back to Burst trie