Proofs: Packed memory array
These are the human proofs of Packed memory array, at full length.
The packed memory array keeps the keys sorted, always has room, and every operation ends full
This proof shows: correctness, termination.
We use the pseudocode of the page. The array has capacity , a power of two, and segments of cells with dividing , so the windows at each height are well defined: the aligned runs of cells, and the window at height is the whole array. The thresholds satisfy for all . Let the key sequence be the keys of slots read from left to right, skipping gaps.
Invariant (I). The key sequence is strictly increasing, and it is the set stored.
Lemma 1 (search). If (I) holds, the binary search of line L1 returns the position of the largest key at most , or if there is none.
Proof. The search keeps and the property: every key at a position before is at most , and every key at a position at or after is larger than . This holds at the start with , . In a pass, let be the midpoint and the first position at or after , before , that holds a key. If there is none, the cells from to are gaps, so setting keeps the property. If the key at is at most , then by (I) all keys before are smaller than , so setting keeps it. If , all keys after are larger, and the cells from to are gaps, so setting keeps it. Each pass makes smaller, since and , so the loop ends with . Then the keys before are exactly the keys at most , and the last of them, found by the scan to the left over gaps, is the largest such key.
Lemma 2 (insert). If (I) holds and is absent, INSERT adds , and (I) holds after it.
Proof. Let be the position from Lemma 1 (use segment 0 if ). In line L5, the window holds position (or position 0). All keys before are at positions before or at , so they are at most the predecessor of , which is less than ; all keys after are after , so they are larger than by Lemma 1. REBALANCE (line L12) collects the keys of in order, adds at its place, and writes them back in order. The test of line L4 gives , so there are enough cells, and the spread positions for are distinct and increasing because . So the new key sequence is the old keys before , then the keys of with , then the old keys after : strictly increasing, with added. If no window passes the test, RESIZE (line L13) collects all keys in order with added, and picks a capacity , so the spread fits, and it is in order.
Lemma 3 (delete). If (I) holds, DELETE removes if it is present and changes nothing otherwise, and (I) holds after it.
Proof. By Lemma 1, line L7 finds if it is present. Making its cell a gap removes from the key sequence and keeps it increasing. A later REBALANCE of a window rewrites its keys in the same order in the same window, which keeps (I), as does a RESIZE, by the argument of Lemma 2 with no key added.
Range and membership. By (I), range(a, b) starts at the first key at least , found from Lemma 1, and reads the keys in increasing order, stopping at the first key larger than ; so it returns exactly the keys in . contains(k) is true exactly when the predecessor of is .
Termination. The loops of lines L2 and L8 run over at most heights. REBALANCE and RESIZE are single passes over a finite list; the capacity loop in RESIZE doubles until it passes a finite bound. The binary search ends by Lemma 1. So every operation ends.
The structure stays valid. After a RESIZE, is a power of two and is recomputed as a power of two at most , so divides . Every window holds at most its size in keys, because a write only puts keys at distinct cells.
The empty array satisfies (I), and by Lemmas 2 and 3, every update keeps it; inserting a present key changes nothing. So (I) holds after every sequence of operations, and the answers of all queries are right.