Proofs: Dynamic bit vector
These are the human proofs of Dynamic bit vector, at full length.
Correctness of the dynamic bit vector full
This proof shows: correctness.
For a node , let be the concatenation of the chunks of its subtree in in-order, with empty. The invariants are:
- (I1) ;
- (I2) and is the number of 1s in , for every node .
By the definition of in-order, .
RANK1. Claim: at the start of each iteration, the answer equals plus the number of 1s in the first bits of , and . Initially is the root, , and this is the definition of by (I1). Let , known from (I2). If , the first bits of are the first bits of , so moving left keeps the claim. If , the first bits are all of , with ones by (I2), and the first bits of the chunk; line L4 returns exactly this plus . Otherwise the first bits contain all of and the chunk, and then the first bits of ; line L5 adds the 1s of the first two parts to and moves right, keeping the claim. In this case , so the right subtree has at least one bit and is not nil. Each iteration moves one level down, so the loop ends, and it ends by line L4 because excludes reaching nil.
SELECT1. Claim: the answer is plus the position of the -th 1 in , and . The three cases split into the same three parts: the -th 1 is in the left part if , in the chunk if is at most that plus the chunk's 1s, and otherwise in the right part, where it is the -th 1, with the chunk's 1s, and its position is shifted by . Line L10 returns the position in the chunk shifted by .
INSERT. The search of line L12 is the walk of RANK1, which by the same argument stops at the node and offset such that position of is offset of , taking the last chunk with when . Inserting at offset turns into by (I1), since the chunks before in in-order hold exactly the bits before it. The nodes whose contains are exactly the ancestors of and itself, the path, and line L14 restores (I2) for them; other nodes are unchanged. If line L15 splits the chunk into , keeping in and putting in a new node placed immediately after in in-order, the concatenation is unchanged, so (I1) holds, and the tree's insertion routine, here a split at the boundary after followed by two treap merges, recomputes the counts of every node it touches, so (I2) holds.
DELETE. Symmetric: removing the bit at offset of removes , line L18 fixes the path, and removing an empty node does not change any concatenation. The removal splits the tree at the boundary where the empty chunk sits, which places it first in the right part, and removes the leftmost node of that part; the treap routines recompute the counts of the nodes they touch.
Height. The structure is a treap with independent random priorities over its chunks, so its expected height is for chunks, and all operations are expected plus the work inside one chunk.