Algorithm Search⌘K

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 xx, let S(x)S(x) be the concatenation of the chunks of its subtree in in-order, with S(nil)S(\text{nil}) empty. The invariants are:

  • (I1) S(root)=BS(\text{root}) = B;
  • (I2) size(x)=∣S(x)∣\text{size}(x) = |S(x)| and ones(x)\text{ones}(x) is the number of 1s in S(x)S(x), for every node xx.

By the definition of in-order, S(x)=S(left(x)) chunk(x) S(right(x))S(x) = S(\text{left}(x))\,\text{chunk}(x)\,S(\text{right}(x)).

RANK1. Claim: at the start of each iteration, the answer equals rr plus the number of 1s in the first ii bits of S(x)S(x), and 0≤i≤∣S(x)∣0 \le i \le |S(x)|. Initially xx is the root, r=0r = 0, and this is the definition of rank1(i)\text{rank}_1(i) by (I1). Let ℓ=∣S(left(x))∣\ell = |S(\text{left}(x))|, known from (I2). If i<ℓi < \ell, the first ii bits of S(x)S(x) are the first ii bits of S(left(x))S(\text{left}(x)), so moving left keeps the claim. If ℓ≤i≤ℓ+∣chunk(x)∣\ell \le i \le \ell + |\text{chunk}(x)|, the first ii bits are all of S(left(x))S(\text{left}(x)), with ones(left(x))\text{ones}(\text{left}(x)) ones by (I2), and the first i−ℓi - \ell bits of the chunk; line L4 returns exactly this plus rr. Otherwise the first ii bits contain all of S(left(x))S(\text{left}(x)) and the chunk, and then the first i−ℓ−∣chunk(x)∣i - \ell - |\text{chunk}(x)| bits of S(right(x))S(\text{right}(x)); line L5 adds the 1s of the first two parts to rr and moves right, keeping the claim. In this case i>ℓ+∣chunk(x)∣i > \ell + |\text{chunk}(x)|, 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 i≤∣S(x)∣i \le |S(x)| excludes reaching nil.

SELECT1. Claim: the answer is base\text{base} plus the position of the jj-th 1 in S(x)S(x), and 1≤j≤ones(x)1 \le j \le \text{ones}(x). The three cases split S(x)S(x) into the same three parts: the jj-th 1 is in the left part if j≤ones(left(x))j \le \text{ones}(\text{left}(x)), in the chunk if jj is at most that plus the chunk's 1s, and otherwise in the right part, where it is the (j−ones(left(x))−c)(j - \text{ones}(\text{left}(x)) - c)-th 1, with cc the chunk's 1s, and its position is shifted by ℓ+∣chunk(x)∣\ell + |\text{chunk}(x)|. Line L10 returns the position in the chunk shifted by base+ℓ\text{base} + \ell.

INSERT. The search of line L12 is the walk of RANK1, which by the same argument stops at the node xx and offset oo such that position ii of BB is offset oo of chunk(x)\text{chunk}(x), taking the last chunk with o=∣chunk∣o = |\text{chunk}| when i=ni = n. Inserting bb at offset oo turns BB into B[0..i−1] b B[i..n−1]B[0..i-1]\, b\, B[i..n-1] by (I1), since the chunks before xx in in-order hold exactly the i−oi - o bits before it. The nodes whose SS contains chunk(x)\text{chunk}(x) are exactly the ancestors of xx and xx itself, the path, and line L14 restores (I2) for them; other nodes are unchanged. If line L15 splits the chunk into c1c2c_1 c_2, keeping c1c_1 in xx and putting c2c_2 in a new node placed immediately after xx in in-order, the concatenation is unchanged, so (I1) holds, and the tree's insertion routine, here a split at the boundary after c1c_1 followed by two treap merges, recomputes the counts of every node it touches, so (I2) holds.

DELETE. Symmetric: removing the bit at offset oo of chunk(x)\text{chunk}(x) removes B[i]B[i], 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 O(lg⁡m)O(\lg m) for mm chunks, and all operations are O(lg⁡n)O(\lg n) expected plus the work inside one chunk. ■\blacksquare

Back to Dynamic bit vector