Algorithm Search⌘K

Proofs: R+-tree

These are the human proofs of R+-tree, at full length.

The R+-tree operations keep the partition invariant, stop, and search reports each rectangle that meets the query exactly once full

This proof shows: correctness, termination.

Regions are half-open, [x0,x1)×[y0,y1)[x_0, x_1) \times [y_0, y_1) with x0<x1x_0 < x_1 and y0<y1y_0 < y_1, where the ends may be infinite; stored rectangles and the query are closed and not empty. A closed rectangle rr meets a region RR if r∩R≠∅r \cap R \ne \emptyset. We prove that the invariant (R+) holds after every operation, that every operation stops, and that SEARCH is correct.

Lemma 1 (cut of a region). For a region RR and a line x=cx = c with x0<c<x1x_0 < c < x_1, the halves RL=[x0,c)×[y0,y1)R_L = [x_0, c) \times [y_0, y_1) and RR=[c,x1)×[y0,y1)R_R = [c, x_1) \times [y_0, y_1) are regions, disjoint, with union RR. A closed rectangle rr meets RR if and only if it meets RLR_L or RRR_R. The same holds for yy.

Proof. Each point of RR has x<cx < c or x≥cx \ge c, not both. Since R=RL∪RRR = R_L \cup R_R, r∩R=(r∩RL)∪(r∩RR)r \cap R = (r \cap R_L) \cup (r \cap R_R). □\square

Lemma 2 (CUT). Let uu satisfy parts (1) to (3) of (R+) in its subtree, for some set SS of rectangles: each leaf below uu holds the rectangles of SS that meet its region. Then CUT(u,axis,c)(u, \text{axis}, c) returns nodes uLu_L and uRu_R with regions RLR_L and RRR_R of Lemma 1, whose subtrees satisfy (1) to (3) for SS, with leaves at the depth of the leaves of uu relative to uu, and each with at most as many entries as uu.

Proof. By induction on the height of uu. A leaf (line L12) gives two leaves with regions RLR_L and RRR_R, each with the entries of uu that meet it. A rectangle of SS that meets RLR_L meets RR, so it is in uu, and so it is in uLu_L: part (2) holds. Each half keeps at most the entries of uu. For an internal node (line L13), a child vv with region [a,b)×…[a, b) \times \ldots goes left if b≤cb \le c, right if a≥ca \ge c, and otherwise, since a<c<ba < c < b, is cut by induction into vLv_L and vRv_R with regions reg(v)∩RL\text{reg}(v) \cap R_L and reg(v)∩RR\text{reg}(v) \cap R_R. The regions of the children of uu partition RR, so the regions of the new children of uLu_L partition R∩RL=RLR \cap R_L = R_L, and the same for uRu_R: part (1) holds. Parts (2) and (3) hold in each child by induction. The number of children of uLu_L is the number of children of uu with a<ca < c, which is at most the number of children of uu. □\square

Guillotine partitions. A partition of a region RR into regions is guillotine if it is {R}\{R\}, or if a line cuts RR into the halves RLR_L and RRR_R of Lemma 1 so that every part lies in RLR_L or in RRR_R, and the parts in each half form a guillotine partition of that half. We call the line the top cut.

Lemma 3 (guillotine facts). (a) If a guillotine partition of RR has s≥2s \ge 2 parts, its top cut is at a side of a part, lies strictly inside RR, crosses no part, and has nL,nR≥1n_L, n_R \ge 1 parts on its sides with nL+nR=sn_L + n_R = s. (b) The intersection of a guillotine partition of RR with a half RLR_L given by any line strictly inside RR (parts that cross the line replaced by their two halves, parts outside dropped) is a guillotine partition of RLR_L. (c) Replacing one part of a guillotine partition by a guillotine partition of that part gives a guillotine partition.

Proof. (a) The parts in RLR_L cover RLR_L, which is not empty, so at least one part lies on each side; a part in RLR_L that touches the line has its upper side at the line. (b) By induction on the number of parts. If the top cut is parallel to the new line, or the new line misses one of its halves, the new line meets one or both halves, and we apply induction in each; otherwise the top cut, restricted to RLR_L, is a cut of RLR_L, and we apply induction to each half. In every case the result is built by cuts. (c) By induction on the cut tree: the replaced part is a leaf of the tree, and we hang the tree of its partition below that leaf. □\square

Lemma 4 (children are guillotine). In every internal node, the regions of the children form a guillotine partition of the region of the node.

Proof. We show that every operation keeps this. A new root made at line L8 has as children the pieces of a SPLIT-ALL of a node of the same region, and SPLIT-ALL makes its pieces by cuts, so they form a guillotine partition. At line L7, a child is replaced by the pieces of its SPLIT-ALL, a guillotine partition of the child, which keeps the property by Lemma 3(c). A CUT of an internal node uu (line L13) gives to uLu_L the children of uu intersected with RLR_L, which is guillotine by Lemma 3(b); a child cut downward is itself an internal node or a leaf, and its own children are treated the same way, by induction. DELETE does not change regions. □\square

Lemma 5 (SPLIT-ALL). Let uu satisfy (1) to (3) for SS. Then SPLIT-ALL(u)(u) stops and returns nodes whose regions partition the region of uu by cuts, each satisfying (1) to (3) for SS. Every internal node returned has at most MM children, and every leaf returned with more than MM entries has no good cut. With clean cuts only, on an internal node with s>M≥2s > M \ge 2 children, it returns fewer than ss pieces, each with at most MM children.

Proof. A good cut found by CHOOSE-CUT (lines L10 and L11) has 0<nL,nR<size(u)0 < n_L, n_R < \text{size}(u), where nLn_L and nRn_R count exactly the entries that go to each side by Lemma 2: the leaf entries with x1<cx_1 < c meet RLR_L and those with x2≥cx_2 \ge c meet RRR_R, and the children with a<ca < c go left and with b>cb > c go right. So both pieces are strictly smaller than uu, and the recursion stops. By Lemmas 1 and 2, the pieces partition the region of uu and satisfy (1) to (3). A node is returned unchanged only if it has at most MM entries or no good cut. An internal node with more than MM children has a good cut, by Lemma 4 and Lemma 3(a), so it is never returned with more than MM children; a leaf with more than MM entries is returned only with no good cut. With clean cuts only, the internal nodes in the recursion stay guillotine by Lemma 3(b), so a clean good cut exists while a node has more than MM children, and every cut splits the tt children of a node into two groups with sizes summing to tt. The pieces are the leaves of a binary tree of cuts in which each cut node has more than M≥2M \ge 2 children. The two pieces of the last cut on any branch have sizes summing to more than 22, so not every piece has one child, and the number of pieces is less than ss. □\square

The nodes below a returned node keep their properties. A piece of an internal node made by a downward cut has at most as many children as the node, by Lemma 2, so at most MM. A piece of a leaf ww with no good cut also has no good cut: its region lies in that of ww, so every candidate line strictly inside the piece is a candidate for ww, and if all entries of ww reach one side of the line, so do all entries of the piece. A piece of a leaf with at most MM entries has at most MM. So part (4) holds in the whole tree after each SPLIT-ALL, given that it held before.

INSERT. Let (R+) hold for SS and insert rr. Claim: the call on a node uu returns nodes whose regions partition the region of uu by cuts, whose subtrees satisfy (R+) for S∪{r}S \cup \{r\}, with leaves at the old depth. By induction on height. At a leaf, rr is added if and only if the walk reached it. The walk goes into every child whose region meets rr (line L5), and by part (1) the union of the regions of the children is the region of the parent, so the leaves reached are exactly those whose regions meet rr. So each leaf holds the rectangles of S∪{r}S \cup \{r\} that meet it (line L6). At an internal node, each child that rr meets is replaced by the pieces of the recursive call, whose regions partition the region of the child; so the children still partition the region of uu. Then SPLIT-ALL (line L7) keeps (R+) by Lemma 5 and the remark after it. At the root, if q≥2q \ge 2 pieces come back, line L8 makes a new root over them. Its region is the plane, the pieces partition it, and every leaf goes one level deeper, so (1) to (3) hold. If q≤Mq \le M the loop ends. Otherwise SPLIT-ALL with clean cuts returns fewer than qq pieces, each with at most MM children, by Lemma 5 with Lemma 4. So the number of pieces strictly decreases from one pass of line L8 to the next, and the loop ends with one root, and (R+) holds for S∪{r}S \cup \{r\}.

DELETE. The walk of line L14 reaches every leaf whose region meets rr, by the argument above, and those are exactly the leaves that hold rr by part (2). Removing rr from each gives part (2) for S∖{r}S \setminus \{r\}; parts (1) and (3) do not change, and a smaller node still satisfies (4).

SEARCH. Let r∈Sr \in S meet qq, and let p=(max⁡(q.x1,r.x1),max⁡(q.y1,r.y1))p = (\max(q.x_1, r.x_1), \max(q.y_1, r.y_1)). Since rr and qq are closed and meet, p∈r∩qp \in r \cap q. By part (1), applied from the root down, exactly one leaf λ\lambda has pp in its region. Its region meets rr and qq at pp, so rr is stored in λ\lambda by part (2), and every ancestor of λ\lambda has a region that contains pp, so it meets qq and the search goes into it (line L2). At λ\lambda, line L3 sees rr, and line L4 finds pp in the region and reports rr. In every other leaf the search sees rr, pp is not in the region, since the leaf regions are disjoint, so rr is not reported there. A rectangle that does not meet qq is never reported, by the test of line L3. So the output is exactly the rectangles of SS that meet qq, each once.

Termination. SEARCH and DELETE visit each node at most once, since the tree is finite. INSERT stops by Lemma 5 and the argument for line L8. ■\blacksquare

Back to R+-tree