Algorithm Search⌘K

Proofs: Circular linked list

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

The circular linked list operations keep the ring and return the right result full

This proof shows: correctness.

Invariant (I). If L.n=0L.n = 0, then $L.last = $ NIL. If n=L.n≥1n = L.n \ge 1, the items are held in distinct nodes v0,…,vn−1v_0, \ldots, v_{n-1} with vi.next=vi+1v_i.next = v_{i+1} for 0≤i<n−10 \le i < n - 1, vn−1.next=v0v_{n-1}.next = v_0, and L.last=vn−1L.last = v_{n-1}. The list held is (ℓ0,…,ℓn−1)(\ell_0, \ldots, \ell_{n-1}) with ℓi=vi.key\ell_i = v_i.key.

For each operation we assume (I) and the precondition, and show (I) for the list that the type asks for. Each push adds 1 to the count and each pop subtracts 1, so we only check the nodes and pointers.

PUSH-FRONT(L,x)(L, x). Line L1 makes a new node vv, distinct from the old nodes. If n=0n = 0, line L2 sets v.next=vv.next = v and L.last=vL.last = v: this is (I) for n=1n = 1 with v0=vv_0 = v, and the list (x)(x). If n≥1n \ge 1, line L3 first sets v.next=L.last.next=vn−1.next=v0v.next = L.last.next = v_{n-1}.next = v_0, then sets vn−1.next=vv_{n-1}.next = v. Define w0=vw_0 = v and wi=vi−1w_i = v_{i-1} for 1≤i≤n1 \le i \le n. Then w0.next=v0=w1w_0.next = v_0 = w_1; wi.next=vi=wi+1w_i.next = v_i = w_{i+1} for 1≤i≤n−11 \le i \le n - 1, since those fields are unchanged; and wn.next=vn−1.next=v=w0w_n.next = v_{n-1}.next = v = w_0. The nodes are distinct and L.last=vn−1=wnL.last = v_{n-1} = w_n. So (I) holds for (x,ℓ0,…,ℓn−1)(x, \ell_0, \ldots, \ell_{n-1}).

PUSH-BACK(L,x)(L, x). After line L4, (I) holds for (x,ℓ0,…,ℓn−1)(x, \ell_0, \ldots, \ell_{n-1}) with nodes w0=v,w1,…,wnw_0 = v, w_1, \ldots, w_n and L.last=wnL.last = w_n. Line L5 sets L.last=wn.next=w0=vL.last = w_n.next = w_0 = v. Read the same ring from L.last.next=w1L.last.next = w_1: define ui=wi+1u_i = w_{i+1} for 0≤i≤n−10 \le i \le n - 1 and un=w0u_n = w_0. Then ui.next=ui+1u_i.next = u_{i+1} for i<ni < n, un.next=w1=u0u_n.next = w_1 = u_0, and L.last=unL.last = u_n. So (I) holds for (ℓ0,…,ℓn−1,x)(\ell_0, \ldots, \ell_{n-1}, x). When n=0n = 0 the ring is the single node vv and L.last=v.next=vL.last = v.next = v, which is (I) for (x)(x).

POP-FRONT(L)(L), n≥1n \ge 1. Line L6 sets v=vn−1.next=v0v = v_{n-1}.next = v_0. If n=1n = 1, then v0=vn−1=L.lastv_0 = v_{n-1} = L.last, line L7 sets $L.last = $ NIL, and (I) holds for the empty list. If n≥2n \ge 2, then v≠L.lastv \ne L.last, and line L7 sets vn−1.next=v0.next=v1v_{n-1}.next = v_0.next = v_1. The nodes v1,…,vn−1v_1, \ldots, v_{n-1} are distinct, vi.next=vi+1v_i.next = v_{i+1} for 1≤i<n−11 \le i < n - 1 (unchanged), vn−1.next=v1v_{n-1}.next = v_1, and L.last=vn−1L.last = v_{n-1}. So (I) holds for (ℓ1,…,ℓn−1)(\ell_1, \ldots, \ell_{n-1}), and line L8 returns ℓ0\ell_0.

ROTATE(L)(L), n≥1n \ge 1. Line L9 sets L.last=vn−1.next=v0L.last = v_{n-1}.next = v_0. No nextnext field changes. Define ui=vi+1u_i = v_{i+1} for 0≤i≤n−20 \le i \le n - 2 and un−1=v0u_{n-1} = v_0. Then ui.next=ui+1u_i.next = u_{i+1} for i<n−1i < n - 1, un−1.next=v1=u0u_{n-1}.next = v_1 = u_0 (or v0=u0v_0 = u_0 when n=1n = 1), and L.last=un−1L.last = u_{n-1}. So (I) holds for (ℓ1,…,ℓn−1,ℓ0)(\ell_1, \ldots, \ell_{n-1}, \ell_0), which is the list with its front moved to the back. ■\blacksquare

Back to Circular linked list