Algorithm Search⌘K

Proofs: LOUDS tree

These are the human proofs of LOUDS tree, at full length.

Correctness of the LOUDS navigation formulas full

This proof shows: correctness.

Let v0,…,vn−1v_0, \ldots, v_{n-1} be the nodes in level order, dkd_k the degree of vkv_k, and L=10 1d00⋯1dn−10L = 10\, 1^{d_0} 0 \cdots 1^{d_{n-1}} 0. Call 1010 the code of the super-root v−1v_{-1} and 1dk01^{d_k} 0 the code of vkv_k.

Fact A. The code of vkv_k starts at position select0(k+1)+1\text{select}_0(k+1) + 1 and ends at select0(k+2)\text{select}_0(k+2). Each code ends with exactly one 0, and the codes of v−1,v0,…,vk−1v_{-1}, v_0, \ldots, v_{k-1} come first, so the (k+1)(k+1)-th 0 ends the code of vk−1v_{k-1} and the (k+2)(k+2)-th 0 ends the code of vkv_k.

Fact B. The (j+1)(j+1)-th 1 of LL stands for vjv_j, meaning that it lies in the code of the parent of vjv_j (with v−1v_{-1} as the parent of v0v_0), and the 1s of one code stand for the children of that node in order. A breadth-first traversal appends the children of vkv_k to its queue when it removes vkv_k, in order; the queue therefore receives v0v_0 (the child of v−1v_{-1}), then the children of v0v_0, then those of v1v_1, and so on. Its output order, which is the level order, is the order of insertion. The 1s of LL are written in the same order: one for v0v_0 in the super-root's code, then one for each child of v0v_0, then of v1v_1, and so on. So the (j+1)(j+1)-th 1 written corresponds to the (j+1)(j+1)-th node inserted, which is vjv_j.

DEGREE. By Fact A, the code of vkv_k occupies positions select0(k+1)+1\text{select}_0(k+1) + 1 to select0(k+2)\text{select}_0(k+2), and all of them but the last are 1s, so dk=select0(k+2)−select0(k+1)−1d_k = \text{select}_0(k+2) - \text{select}_0(k+1) - 1.

CHILD. Let s=select0(k+1)s = \text{select}_0(k+1). The bits before s+1s + 1 contain rank1(s+1)=rank1(s)\text{rank}_1(s + 1) = \text{rank}_1(s) ones, since L[s]=0L[s] = 0. The ii-th bit of the code of vkv_k, for 1≤i≤dk1 \le i \le d_k, is therefore the (rank1(s)+i)(\text{rank}_1(s) + i)-th 1 of LL, and by Fact B it stands for vrank1(s)+i−1v_{\text{rank}_1(s) + i - 1}, the ii-th child of vkv_k. Line L2 rejects i>dki > d_k.

PARENT. For k≥1k \ge 1, let p=select1(k+1)p = \text{select}_1(k+1). By Fact B, pp lies in the code of the parent vjv_j of vkv_k, and j≥0j \ge 0 because only v0v_0 has its 1 in the super-root's code. The 0s before pp are the final 0s of the codes that end before pp, which are those of v−1,v0,…,vj−1v_{-1}, v_0, \ldots, v_{j-1}; the code of vjv_j contains pp and ends after it. So rank0(p)=j+1\text{rank}_0(p) = j + 1 and line L7 returns jj.

NEXT-SIBLING. The siblings of vkv_k are the nodes whose 1s lie in the same code. If L[p+1]=1L[p+1] = 1, that 1 is in the same code (a code has no 0 before its end), it is the (k+2)(k+2)-th 1, and by Fact B it stands for vk+1v_{k+1}, the next child of the same parent. If L[p+1]=0L[p+1] = 0, the code ends at p+1p + 1 and vkv_k is the last child. The same argument with L[p−1]L[p-1] gives PREV-SIBLING for k≥1k \ge 1; for k=0k = 0, p=0p = 0 and the root has no siblings.

CHILD-RANK. With pp as above and r=rank0(p)r = \text{rank}_0(p), the code containing pp starts at select0(r)+1\text{select}_0(r) + 1, since the rr-th 0 is the last 0 before pp. The bits from there to pp are all 1s, and there are p−select0(r)p - \text{select}_0(r) of them, which is the index of vkv_k among its siblings.

Space. LL has 22 bits for the super-root and dk+1d_k + 1 bits for each vkv_k, in total 2+(n−1)+n=2n+12 + (n - 1) + n = 2n + 1, since the degrees sum to the n−1n - 1 edges. ■\blacksquare

Back to LOUDS tree