Algorithm Search⌘K

Proofs: Point quadtree

These are the human proofs of Point quadtree, at full length.

The point quadtree keeps the quadrant invariant and range search reports exactly the points in the box full

This proof shows: correctness, termination.

We use the names of the pseudocode. Write quad(p,q)=[qx≥px]+2[qy≥py]\text{quad}(p, q) = [q_x \ge p_x] + 2[q_y \ge p_y]. The invariant (Q) says that for each node tt and each point qq in the subtree t.child[i]t.child[i], quad(t.point,q)=i\text{quad}(t.point, q) = i, and that no point is stored twice.

Lemma 1 (regions). Define R(root)=R2R(\text{root}) = \mathbb{R}^2 and, for a node tt with point pp, let R(t.child[i])=R(t)∩Zi(p)R(t.child[i]) = R(t) \cap Z_i(p), where Z0(p)={x<px,y<py}Z_0(p) = \{x < p_x, y < p_y\}, Z1(p)={x≥px,y<py}Z_1(p) = \{x \ge p_x, y < p_y\}, Z2(p)={x<px,y≥py}Z_2(p) = \{x < p_x, y \ge p_y\} and Z3(p)={x≥px,y≥py}Z_3(p) = \{x \ge p_x, y \ge p_y\}. If (Q) holds, every point of the subtree of a node uu lies in R(u)R(u). Proof. By induction on depth: a point qq in the subtree t.child[i]t.child[i] lies in the subtree of tt, so in R(t)R(t), and has quad(t.point,q)=i\text{quad}(t.point, q) = i, which means q∈Zi(t.point)q \in Z_i(t.point). □\square

Search. If (Q) holds and pp is stored at a node vv, then at each proper ancestor tt of vv, the point pp is in the subtree t.child[i]t.child[i] with i=quad(t.point,p)i = \text{quad}(t.point, p), so the path of INSERT from the root reaches vv. If pp is not stored, the path ends at an empty child. Each step goes one level down, so the walk stops after at most hh steps.

INSERT. If the tree is empty, line L1 makes a one-node tree, which satisfies (Q). Otherwise, by the search argument, line L2 stops if pp is stored, so no point is stored twice. Each pass of lines L3 to L5 moves one level down, so the loop stops. When line L4 adds pp as t.child[i]t.child[i], the nodes whose subtrees change are tt and its ancestors, all on the path. At each such node uu, the loop chose the child quad(u.point,p)\text{quad}(u.point, p), and pp is in the subtree of exactly that child; so (Q) holds at uu. Other nodes do not change.

RANGE-SEARCH. Let Q=[ℓx,hx]×[ℓy,hy]Q = [\ell_x, h_x] \times [\ell_y, h_y]. Each reported point is stored and lies in QQ by line L7, and each node is visited at most once, since the calls follow the tree; with no point stored twice, no point is reported twice. Let q∈Qq \in Q be stored at a node vv, and let tt be a proper ancestor of vv, with point pp, such that vv is in the subtree t.child[i]t.child[i]. By (Q), q∈Zi(p)q \in Z_i(p). If qx<pxq_x < p_x then ℓx≤qx<px\ell_x \le q_x < p_x, so WW holds; if qx≥pxq_x \ge p_x then hx≥qx≥pxh_x \ge q_x \ge p_x, so EE holds. In the same way, qy<pyq_y < p_y gives SS and qy≥pyq_y \ge p_y gives NN. So the two tests that line L9 makes for child ii both hold, and the search enters t.child[i]t.child[i]. By induction along the path from the root, the search visits vv, and line L7 reports qq. The search visits each node at most once, so it stops.

DELETE. If pp is not stored, line L10 finds no node, and nothing changes. Otherwise let tt be its node. After line L12, the tree holds exactly the stored points other than pp and those of RR, and it satisfies (Q), since removing a subtree removes points from some subtrees and adds none. Each point of RR is not in the tree at this moment, so line L13 adds it by INSERT, which keeps (Q) and adds exactly that point. After the loop, the tree holds exactly the old set minus pp and satisfies (Q). The loop runs ∣R∣|R| times, so it stops.

Balanced build. Let the points of a group, with distinct xx coordinates, be sorted by (x,y)(x, y), and let pp be the point at index ⌊m/2⌋\lfloor m/2 \rfloor of a group of mm. The points before it have x<pxx < p_x and go west; the points after it have x>pxx > p_x and go east. So the two west quadrants together get ⌊m/2⌋\lfloor m/2 \rfloor points and the two east quadrants ⌈m/2⌉−1≤⌊m/2⌋\lceil m/2 \rceil - 1 \le \lfloor m/2 \rfloor points, and each child group has at most m/2m/2 points. Each child gets exactly the points qq with quad(p,q)=i\text{quad}(p, q) = i, so the tree satisfies (Q), and a node at depth dd (root at depth 0) has at most n/2dn / 2^d points in its subtree, which gives a height of at most ⌊lg⁡n⌋+1\lfloor \lg n \rfloor + 1. ■\blacksquare

Back to Point quadtree