Proofs: Singly linked list
These are the human proofs of Singly linked list, at full length.
The operations of a singly linked list keep its invariant and are correct full
This proof shows: correctness.
We write for the sequence that the list represents when the invariant (I) holds with the nodes .
(I) There are distinct nodes with , for and . If then . If then .
A new node is distinct from each node of the list, because lines L1, L6 and A1 make it fresh. Each operation below starts in a state where (I) holds.
The empty list. A list with and meets (I) with no nodes, and .
Lemma 1 (PUSH-FRONT). After PUSH-FRONT, (I) holds and , where is the sequence before the call.
Proof. Let be the new node, with key . Line L2 sets if , and NIL if . Line L3 sets . No other link changes, so the chain is , of distinct nodes, ending in NIL. If , then was not NIL, line L4 does nothing, and the tail is still the last node. If , then and line L4 sets it to , the only node. Line L5 makes the count .
Lemma 2 (PUSH-BACK). After PUSH-BACK, (I) holds and .
Proof. Let be the new node; line L6 gives it key and next NIL. If , line L7 sets , so the chain is the single node. If , then by (I), and line L8 sets , which extends the chain by one node. In both cases line L9 makes the new node the tail and line L10 the count .
Lemma 3 (POP-FRONT). If , then POP-FRONT returns , and afterwards (I) holds and .
Proof. Line L11 sets and line L12 sets , which is if and NIL if . No other link changes, so the chain from the head is . If the head is not NIL, line L13 does nothing, and is still the last node. If the head is NIL, and line L13 sets the tail to NIL. Line L14 makes the count , and line L15 returns .
Lemma 4 (SEARCH). SEARCH returns the node with the least such that , or NIL if there is none.
Proof. We use this invariant of the loop of line S2: for some with , where means NIL, and no node with has key . Line S1 sets (or NIL, which is when ), with no earlier node, so the invariant holds. If the loop body runs, then and , and line S3 moves to , so the invariant holds for . The index grows by exactly 1 in each pass and cannot pass , because at the test fails. So the loop stops after at most passes. When it stops, either , and by the invariant no node has key , or with and no earlier match. Line S4 returns .
Lemma 5 (INSERT-AFTER). If is a node of , then after INSERT-AFTER, (I) holds and .
Proof. Let be the new node with key . Line A2 sets , which is , or NIL if . Line A3 sets . No other link changes, so the chain is , of distinct nodes, ending in NIL. If , then and line A4 makes , the new last node, the tail. If , the tail is still the last node and line A4 does nothing. Line A5 makes the count .
Lemma 6 (DELETE). DELETE returns false and changes nothing if no node has key . Otherwise, let be the first node with key ; it returns true, and afterwards (I) holds and is with its -th item removed.
Proof. The loop of lines D2 and D3 is the loop of SEARCH, with one more variable. It keeps the invariant of Lemma 4 and also: if , and if . Line D1 makes this true for , and line D3 sets to the old when moves to . By Lemma 4, the loop stops at the first node with key , or at NIL.
If it stops at NIL, line D4 returns false, and no field was written.
Else . If , then , and line D5 sets , the node or NIL. If , then , and line D5 sets , which is or NIL. In both cases, the chain from the head is , of distinct nodes, and it ends in NIL. For the tail: if , then , and line D6 sets the tail to , which is , the new last node, or NIL when and the list is now empty. If , then and is still the last node. Line D7 makes the count , and line D8 returns true.
Theorem. Starting from the empty list, after each finite sequence of the operations PUSH-FRONT, PUSH-BACK, POP-FRONT on a nonempty list, SEARCH, INSERT-AFTER on a node of the list, and DELETE, the invariant (I) holds, and the list represents the sequence that the same operations give on the abstract type, and each result is the one that the abstract type gives.
Proof. By induction on the number of operations. The empty list meets (I) and represents . If (I) holds and the list represents the right sequence before an operation, then Lemmas 1 to 6 show that (I) holds after it, that the new sequence is the one the abstract operation gives, and that the result is correct. SEARCH changes no field, so it keeps (I) trivially.
Cost. Lines L1 to L15 and A1 to A5 have no loop, so each of PUSH-FRONT, PUSH-BACK, POP-FRONT and INSERT-AFTER takes time. By the proof of Lemma 4, the loop of SEARCH, and the same loop in DELETE, makes at most passes, and exactly on a miss, so each takes time in the worst case.