Algorithm Search⌘K

Proofs: Circular buffer

These are the human proofs of Circular buffer, at full length.

The circular buffer operations keep the queue in the right cells full

This proof shows: correctness.

Setting. A buffer BB has an array A[0..N−1]A[0..N-1] with N≥1N \ge 1, an index hh and a count nn. For 0≤i<N0 \le i < N, write ci=(h+i) mod Nc_i = (h + i) \bmod N.

Lemma. For a fixed hh, the cells c0,…,cN−1c_0, \ldots, c_{N-1} are distinct, so they are all NN cells.

Proof. If ci=cjc_i = c_j with 0≤i<j<N0 \le i < j < N, then NN divides j−ij - i, which is between 1 and N−1N - 1. That is impossible. □\square

Invariant (I). 0≤h<N0 \le h < N, 0≤n≤N0 \le n \le N, and the queue held is Q=⟨A[c0],…,A[cn−1]⟩Q = \langle A[c_0], \ldots, A[c_{n-1}] \rangle.

(I) holds for a new buffer with h=0h = 0 and n=0n = 0. For each operation, assume (I) and the precondition, and write Q=⟨q0,…,qn−1⟩Q = \langle q_0, \ldots, q_{n-1} \rangle with qi=A[ci]q_i = A[c_i].

ENQUEUE(B,x)(B, x). If n=Nn = N, line L1 stops with an error and nothing changes. Otherwise n<Nn < N. Line L2 writes xx into cell cnc_n. By the lemma, cnc_n differs from c0,…,cn−1c_0, \ldots, c_{n-1}, so the items q0,…,qn−1q_0, \ldots, q_{n-1} stay in their cells. Line L3 sets the count to n+1≤Nn + 1 \le N, and hh does not change. So the new queue is ⟨q0,…,qn−1,x⟩\langle q_0, \ldots, q_{n-1}, x \rangle, and (I) holds.

DEQUEUE(B)(B). If n=0n = 0, line L4 stops with an error. Otherwise line L5 reads x=A[c0]=q0x = A[c_0] = q_0. Line L6 sets h′=(h+1) mod Nh' = (h + 1) \bmod N, which is in [0,N)[0, N), and n′=n−1≥0n' = n - 1 \ge 0. No cell is written. The new cells are ci′=(h′+i) mod N=(h+1+i) mod N=ci+1c'_i = (h' + i) \bmod N = (h + 1 + i) \bmod N = c_{i+1}. So the new queue is ⟨A[c1],…,A[cn−1]⟩=⟨q1,…,qn−1⟩\langle A[c_1], \ldots, A[c_{n-1}] \rangle = \langle q_1, \ldots, q_{n-1} \rangle, and line L7 returns q0q_0.

PUSH-FRONT(B,x)(B, x), n<Nn < N. Line L8 sets h′=(h−1) mod Nh' = (h - 1) \bmod N, taken in [0,N)[0, N), writes xx into A[h′]A[h'] and sets n′=n+1n' = n + 1. The new cells are c0′=h′c'_0 = h' and ci′=(h−1+i) mod N=ci−1c'_i = (h - 1 + i) \bmod N = c_{i-1} for i≥1i \ge 1. The cell h′=cN−1h' = c_{N-1} is not one of c0,…,cn−1c_0, \ldots, c_{n-1} because n≤N−1n \le N - 1, by the lemma. So the write does not touch an item, and the new queue is ⟨x,q0,…,qn−1⟩\langle x, q_0, \ldots, q_{n-1} \rangle.

POP-BACK(B)(B), n≥1n \ge 1. Line L9 sets n′=n−1n' = n - 1, and line L10 returns A[(h+n′) mod N]=A[cn−1]=qn−1A[(h + n') \bmod N] = A[c_{n-1}] = q_{n-1}. No cell is written and hh does not change, so the new queue is ⟨q0,…,qn−2⟩\langle q_0, \ldots, q_{n-2} \rangle.

GET(B,i)(B, i), 0≤i<n0 \le i < n. Line L11 returns A[ci]=qiA[c_i] = q_i, and nothing changes. ■\blacksquare

Back to Circular buffer