Algorithm Search⌘K

Proofs: Array

These are the human proofs of Array, at full length.

The array operations keep the list and return the right result full

This proof shows: correctness.

Setting. The array has capacity N≥0N \ge 0, a count nn and cells A[0…N−1]A[0 \ldots N-1]. The list held by the array is L=(A[0],…,A[n−1])L = (A[0], \ldots, A[n-1]).

Invariant (I). 0≤n≤N0 \le n \le N.

We show that each operation, started in a state where (I) holds and its precondition holds, ends in a state where (I) holds, holds the list that the list type asks for, and returns the right value. We write L=(ℓ0,…,ℓn−1)L = (\ell_0, \ldots, \ell_{n-1}) for the list before the operation, so ℓk\ell_k is the old value of A[k]A[k].

GET(A,i)(A, i), 0≤i<n0 \le i < n. Line L1 returns A[i]=ℓiA[i] = \ell_i, the item at position ii. Nothing is written, so LL and (I) do not change.

SET(A,i,x)(A, i, x), 0≤i<n0 \le i < n. Line L2 writes only cell ii, so the new list is (ℓ0,…,ℓi−1,x,ℓi+1,…,ℓn−1)(\ell_0, \ldots, \ell_{i-1}, x, \ell_{i+1}, \ldots, \ell_{n-1}), and nn does not change.

INSERT(A,i,x)(A, i, x), 0≤i≤n<N0 \le i \le n < N. The goal is the list (ℓ0,…,ℓi−1,x,ℓi,…,ℓn−1)(\ell_0, \ldots, \ell_{i-1}, x, \ell_i, \ldots, \ell_{n-1}) of length n+1n + 1.

Loop invariant (J). At each test of line L3 with the current value jj, where i≤j≤ni \le j \le n: A[k]=ℓkA[k] = \ell_k for 0≤k≤j−10 \le k \le j - 1, and A[k]=ℓk−1A[k] = \ell_{k-1} for j+1≤k≤nj + 1 \le k \le n.

  1. Initialization. Before the first test j=nj = n. No cell has been written, so A[k]=ℓkA[k] = \ell_k for k≤n−1k \le n - 1, and the second range n+1≤k≤nn + 1 \le k \le n is empty. All indices used are less than NN because n<Nn < N.
  2. Maintenance. Assume (J) at the test with value j>ij > i. Line L4 sets A[j]←A[j−1]A[j] \leftarrow A[j-1]. Since j−1≤j−1j - 1 \le j - 1, the first part of (J) gives A[j−1]=ℓj−1A[j-1] = \ell_{j-1}, so now A[j]=ℓj−1A[j] = \ell_{j-1}. No other cell changes. Then jj becomes j′=j−1j' = j - 1. For k≤j′−1=j−2k \le j' - 1 = j - 2 the cell is unchanged and equals ℓk\ell_k. For j′+1=j≤k≤nj' + 1 = j \le k \le n: A[j]=ℓj−1A[j] = \ell_{j-1} was just written, and for k≥j+1k \ge j + 1 the cell is unchanged and equals ℓk−1\ell_{k-1} by (J). So (J) holds for j′j'.
  3. Termination. Each iteration decreases jj by exactly 1, from nn, and the loop stops at the first test with j=ij = i. So it runs exactly n−in - i times. At exit, (J) with j=ij = i gives A[k]=ℓkA[k] = \ell_k for k<ik < i and A[k]=ℓk−1A[k] = \ell_{k-1} for i+1≤k≤ni + 1 \le k \le n.

Line L5 writes xx to A[i]A[i], which is the only index not covered by the two ranges. Line L6 sets the count to n+1≤Nn + 1 \le N, so (I) holds. The cells A[0…n]A[0 \ldots n] now read ℓ0,…,ℓi−1,x,ℓi,…,ℓn−1\ell_0, \ldots, \ell_{i-1}, x, \ell_i, \ldots, \ell_{n-1}, which is the goal.

DELETE(A,i)(A, i), 0≤i<n0 \le i < n. The goal is to return ℓi\ell_i and to leave the list (ℓ0,…,ℓi−1,ℓi+1,…,ℓn−1)(\ell_0, \ldots, \ell_{i-1}, \ell_{i+1}, \ldots, \ell_{n-1}) of length n−1n - 1. Line L7 saves x=ℓix = \ell_i before any cell is written.

Loop invariant (K). At each test of line L8 with the current value jj, where i≤j≤n−1i \le j \le n - 1: A[k]=ℓkA[k] = \ell_k for k<ik < i and for j≤k≤n−1j \le k \le n - 1, and A[k]=ℓk+1A[k] = \ell_{k+1} for i≤k≤j−1i \le k \le j - 1.

  1. Initialization. Before the first test j=ij = i, no cell has been written, and the middle range is empty.
  2. Maintenance. Assume (K) at the test with value j≤n−2j \le n - 2. Line L9 sets A[j]←A[j+1]A[j] \leftarrow A[j+1]. Since j+1j + 1 lies in [j,n−1][j, n-1], (K) gives A[j+1]=ℓj+1A[j+1] = \ell_{j+1}. So now A[j]=ℓj+1A[j] = \ell_{j+1}, and the middle range grows to [i,j][i, j]. The cells from j+1j + 1 to n−1n - 1 are unchanged. So (K) holds for j+1j + 1.
  3. Termination. Each iteration increases jj by exactly 1, from ii, and the loop stops at the first test with j=n−1j = n - 1. So it runs exactly n−1−in - 1 - i times. At exit, (K) with j=n−1j = n - 1 gives A[k]=ℓk+1A[k] = \ell_{k+1} for i≤k≤n−2i \le k \le n - 2 and A[k]=ℓkA[k] = \ell_k for k<ik < i.

Line L10 sets the count to n−1≥0n - 1 \ge 0, so (I) holds, and the list A[0…n−2]A[0 \ldots n-2] is the goal. Line L11 returns x=ℓix = \ell_i.

SEARCH(A,x)(A, x). Loop invariant: at the test of line S1 with value ii, no ℓk\ell_k with k<ik < i equals xx. It holds for i=0i = 0, and line S2 keeps it, because it returns when ℓi=x\ell_i = x and otherwise ℓi≠x\ell_i \ne x. If line S2 returns ii, then ℓi=x\ell_i = x and no earlier item equals xx, so ii is the first index of xx. If the loop ends, then i=ni = n and no item equals xx, so NIL is right. The loop runs at most nn times because ii increases by 1 each time. Nothing is written. ■\blacksquare

Back to Array