Algorithm Search⌘K

Proofs: Forward star

These are the human proofs of Forward star, at full length.

BUILD makes a valid forward and reverse star and the queries list the arcs of each vertex full

This proof shows: correctness, termination.

Let AA be the input list of mm arcs (t,h,data)(t, h, \mathit{data}) with 0≤t,h<n0 \le t, h < n; repeats are allowed. Write d+(i)d^+(i) and d−(j)d^-(j) for the number of arcs of AA with tail ii and with head jj. The invariant (F) is (F1), arcs sorted by tail with point\mathit{point} marking the blocks, and (F2), trace\mathit{trace} split by rpoint\mathit{rpoint} into increasing segments of the names of the arcs into each vertex.

Lemma 1 (prefix counts). If p[i]p[i] is the number of keys less than ii for 0≤i≤n0 \le i \le n, then p[0]=0p[0] = 0, p[n]p[n] is the number of keys, pp is non-decreasing, and p[i+1]−p[i]p[i+1] - p[i] is the number of keys equal to ii.

Proof. Direct from the definition, since each key is in {0,…,n−1}\{0, \ldots, n-1\}. □\square

Lemma 2 (line L1). After line L1, the arcs are a permutation of AA, named 0,…,m−10, \ldots, m-1, with non-decreasing tails, and arcs with the same tail are in their input order.

Proof. Line L1 is a counting sort by tail. Let s[i]s[i] be the number of arcs with tail less than ii. The arcs with tail ii are written, in input order, into the slots s[i],s[i]+1,…s[i], s[i] + 1, \ldots, since the counter of tail ii starts at s[i]s[i] and is increased after each write. By Lemma 1 these slots form the block [s[i],s[i+1])[s[i], s[i+1]) of length d+(i)d^+(i), and the blocks of different tails are disjoint and cover [0,m)[0, m). So each slot is written once, the result is a permutation of AA, tails increase from block to block, and each block keeps the input order. The loop has mm steps, so it stops. □\square

By Lemma 2 and Lemma 1 applied to the tails, line L2 sets point[i]=s[i]\mathit{point}[i] = s[i], the start of the block of tail ii, and the arcs out of ii are the names in [point[i],point[i+1])[\mathit{point}[i], \mathit{point}[i+1]). So (F1) holds.

Lemma 3 (lines L3 to L6). After line L6, (F2) holds.

Proof. By Lemma 1 applied to the heads, line L3 gives rpoint\mathit{rpoint} with rpoint[0]=0\mathit{rpoint}[0] = 0, rpoint[n]=m\mathit{rpoint}[n] = m, non-decreasing, and segments of lengths d−(j)d^-(j). We claim that before step ee of the loop of line L5, for each jj, rpos[j]=rpoint[j]+kj\mathit{rpos}[j] = \mathit{rpoint}[j] + k_j, where kjk_j is the number of names below ee with head jj, and slots rpoint[j],…,rpos[j]−1\mathit{rpoint}[j], \ldots, \mathit{rpos}[j] - 1 hold these names in increasing order. Line L4 makes this true for e=0e = 0. Step ee writes ee, which is larger than all names written before, into slot rpos[j]\mathit{rpos}[j] for j=head[e]j = \mathit{head}[e], and increases rpos[j]\mathit{rpos}[j], which keeps the claim for e+1e + 1. Since kj≤d−(j)k_j \le d^-(j), each write stays in the segment of jj. After step m−1m - 1, kj=d−(j)k_j = d^-(j) for each jj, so each segment is full, holds exactly the names of the arcs into jj, each once, in increasing order. The loop has mm steps, so it stops. □\square

Theorem. After BUILD, (F) holds; OUT-ARCS(i)(i) outputs exactly the names of the arcs out of ii, each once; IN-ARCS(j)(j) outputs exactly the names of the arcs into jj, each once; and OUT-DEGREE and IN-DEGREE return d+(i)d^+(i) and d−(j)d^-(j). Each query stops.

Proof. (F) holds by Lemma 2 with line L2, and Lemma 3. Line L7 outputs the names in [point[i],point[i+1])[\mathit{point}[i], \mathit{point}[i+1]), which by (F1) are the arcs out of ii. Line L8 outputs the segment of jj of trace\mathit{trace}, which by (F2) lists the arcs into jj, each once. Lines L9 and L10 return the lengths of the block and of the segment, which by Lemma 1 are d+(i)d^+(i) and d−(j)d^-(j). Each query runs over a finite range. Since both stars return names and the data of an arc is stored once, at its name, a write to the data of arc ee is read back the same way through either star. ■\blacksquare

Back to Forward star