Balanced, Augmented and Persistent TreesIntroduction and ContextTree data structures organize information hierarchically while supporting searching, insertion, deletion, and ordered traversal. An ordinary binary search tree (BST) can provide efficient operations, but its performance depends on its height. If keys are inserted in sorted order, a BST may degenerate into a linked list, making search, insertion, and deletion take Θ(n) time. Balanced trees control height. Augmented trees store additional information at nodes so that operations such as interval overlap testing or range aggregation become efficient. Persistent trees preserve earlier versions after updates, which is valuable in databases, functional programming, audit systems, and temporal analytics. Multiway trees, particularly B-trees and B+ trees, are optimized for secondary storage and reduce expensive block accesses. This chapter studies the invariants, algorithms, complexity, implementation trade-offs, and appropriate applications of AVL, red-black, splay, interval, segment, Fenwick, B/B+ and persistent trees. Learning ObjectivesBy the end of this chapter, a learner should be able to: - explain why tree height determines ordered-operation performance;
- maintain AVL and red-black invariants after updates;
- compare strict balancing with amortized self-adjustment;
- design augmented trees for interval and range queries;
- distinguish segment trees from Fenwick trees;
- select B/B+ trees for block-oriented storage;
- explain path copying and version sharing in persistent trees;
- analyze space, time, locality, concurrency, and implementation trade-offs.
1. Height, Invariants, and ComplexityFor a binary tree with n nodes, the height h is the number of edges on the longest root-to-leaf path. A search follows one path, so its running time is Θ(h). A balanced binary tree has h = O(log n), whereas an unbalanced tree may have h = Θ(n). An invariant is a property that must remain true before and after every operation. Examples include: - BST ordering: every key in a left subtree is less than the node key, and every key in a right subtree is greater, subject to a stated duplicate policy;
- AVL balance: the height difference of the two child subtrees is at most one;
- red-black coloring conditions;
- a subtree aggregate equals the combination of its children and its own value.
Rotations preserve in-order key order while changing local structure. A left rotation and a right rotation each take Θ(1) time. They are the fundamental repair operations for many balanced trees. 2. AVL TreesAn AVL tree is a height-balanced BST. For every node v, define its balance factor as: BF(v) = height(left(v)) − height(right(v)) The AVL invariant is −1 ≤ BF(v) ≤ 1. Heights must be updated after insertion or deletion, and a node whose balance factor becomes ±2 requires restructuring. RotationsFour configurations occur: | Configuration | Repair |
|---|
| Left-left | Right rotation | | Right-right | Left rotation | | Left-right | Left rotation on child, then right rotation | | Right-left | Right rotation on child, then left rotation |
Insertion follows the BST path, updates heights while returning toward the root, and repairs the first unbalanced ancestor. Deletion may cause imbalance at several ancestors, so repair can continue to the root. The minimum number N(h) of nodes in an AVL tree of height h satisfies: N(h) = 1 + N(h − 1) + N(h − 2) with suitable base cases such as N(0) = 1 and N(1) = 2 when height counts edges. This Fibonacci-like recurrence implies h = O(log n). Thus search, insertion, and deletion are O(log n) in the worst case. AVL trees generally have shorter paths than red-black trees, but deletion and height maintenance can require more restructuring. 3. Red-Black TreesA red-black tree is a BST whose nodes are colored red or black. A common formulation uses these invariants: - Every node is red or black.
- The root is black.
- Every null leaf (conceptual sentinel) is black.
- A red node cannot have a red child.
- Every path from a node to a descendant null leaf contains the same number of black nodes.
The number of black nodes on such a path is called its black height. The invariants imply h = O(log n); specifically, a red-black tree with n internal nodes has height at most approximately 2 log₂(n + 1). Insertion initially creates a red node. If its parent is black, no violation occurs. If its parent is red, recoloring or rotations are applied according to the uncle's color and the configuration. Deletion is more difficult because removing a black node can reduce the black height of one path. Standard fix-up procedures use sibling color, sibling-child colors, rotations, and recoloring. Compared with AVL trees, red-black trees permit somewhat greater height but often require fewer rotations during updates. They are widely used for ordered maps and sets in standard libraries. Their principal engineering advantages are predictable worst-case bounds and mature implementations; their disadvantages include complicated deletion logic and extra color metadata. 4. Splay Trees and Amortized BalanceA splay tree is a self-adjusting BST with no explicit balance field. After access to a node, the node is moved to the root through rotations. The main patterns are: - zig: one rotation when the node is a child of the root;
- zig-zig: two rotations in the same direction;
- zig-zag: two rotations in opposite directions.
A single operation can take Θ(n), but a sequence of m operations on n nodes has amortized cost O(m log n) under the standard splay-tree analysis. The amortized guarantee does not mean that every individual operation is logarithmic. Splay trees exploit locality. Repeatedly accessed keys become close to the root, making them suitable for caches, symbol tables, adaptive dictionaries, and workloads with temporal or sequential locality. They do not provide strict worst-case latency, and rotations can interfere with read-sharing and concurrent access. They also have no direct guarantee that all paths remain short at every instant. 5. Augmented Search TreesAugmentation stores a derived attribute at each node. The attribute must be maintainable from local information. If a node stores key x, value a, and aggregate A, a typical recurrence is: A(v) = combine(A(left(v)), a(v), A(right(v))) The combine operation should be associative when the aggregate is intended to support range decomposition. Examples include sum, minimum, maximum, count, bitwise OR, and interval maximum endpoint. For rotations to preserve correctness, every changed node must have its augmented field recomputed after its children are changed. This is known as the augmentation or rotation-maintenance condition. An augmented balanced BST can therefore support ordered updates in O(log n) while answering suitable queries in O(log n). 6. Interval TreesAn interval is typically represented as [low, high], where low ≤ high. An interval tree is commonly implemented as an augmented BST ordered by low. Each node stores: - its interval;
- the maximum high endpoint in its subtree.
For node v: maxHigh(v) = max(high(v), maxHigh(left(v)), maxHigh(right(v))) The query for an interval q = [q_low, q_high] seeks an interval that overlaps q. Two closed intervals overlap when: low ≤ qhigh and qlow ≤ high If the left child exists and its maxHigh is at least q_low, the search may need to visit the left subtree. Otherwise, the left subtree cannot contain an overlapping interval, and the search proceeds right. With a balanced underlying tree, finding one overlap is O(log n) in typical non-reporting search, while reporting k overlaps takes O(log n + k) under appropriate traversal and output assumptions. The endpoint convention matters. For half-open intervals [low, high), overlap uses strict comparison at the upper boundary. Mixing closed and half-open conventions is a common correctness error. Interval trees are useful for booking conflicts, compiler live-range analysis, memory allocation, geographic regions, and scheduling. If the query is instead “which intervals cover a point?” or requires sophisticated stabbing-count operations, alternative structures such as interval skip lists or segment trees may be more suitable. 7. Segment TreesA segment tree recursively partitions an indexed domain into disjoint ranges. For an array of n elements, the root represents the entire range, and each internal node represents the union of two child ranges. A query range is decomposed into O(log n) canonical nodes, and a point update affects O(log n) nodes. For range sums, each node stores: sum(node) = sum(left child) + sum(right child) For range minimum, the operation is min rather than addition. The operation must support the intended decomposition; associative operations are especially convenient. A traditional segment tree uses O(n) storage, commonly bounded by 4n in a simple recursive array implementation, though compact iterative layouts can use near 2n storage. Lazy propagation supports range updates without immediately visiting every leaf. Each node stores a deferred tag. For example, under range addition, a node covering length L with pending increment Δ changes its sum by L × Δ. The tag is propagated to children only when necessary. With correct composition of lazy tags, range update and range query both take O(log n). Segment trees are powerful but comparatively memory-intensive and implementation-sensitive. They support richer operations than Fenwick trees, including minimum, maximum, assignment, addition, and combinations, provided update-tag interactions are correctly defined. 8. Fenwick TreesA Fenwick tree, or binary indexed tree, stores partial aggregates in an array. For an index i, the quantity lowbit(i) is the value of its least significant set bit: lowbit(i) = i & (−i) The Fenwick entry at i represents a range ending at i whose length is lowbit(i). Prefix queries repeatedly subtract lowbit(i); point updates repeatedly add lowbit(i). Both operations take O(log n), and storage is O(n). For an additive array, a prefix sum is: prefix(i) = a₁ + a₂ + ⋯ + aᵢ A range sum [l, r] is prefix(r) − prefix(l − 1). A Fenwick tree is especially attractive because it has low constant factors, compact memory use, and good cache locality. Its basic form naturally supports point updates and prefix sums, not arbitrary range updates and arbitrary range queries. Variants using two Fenwick trees can support range addition with prefix-sum queries, but these require careful derivation and assumptions about the operation. 9. B-Trees and B+ TreesBinary trees are not naturally optimized for disks or SSD pages. A storage access transfers a block containing many records, so a multiway tree reduces height and block reads. A B-tree node contains multiple sorted keys and child pointers. If the maximum number of children is m, an internal node has at most m children and, except for the root, at least approximately half full under standard definitions. Exact minimum occupancy conventions vary with whether m denotes maximum children or maximum keys, so implementations must specify the convention. B-tree insertion splits a full child before descending. Deletion may borrow a key from a sibling or merge nodes to preserve minimum occupancy. Search, insertion, and deletion require O(log_m n) node visits, where m is the effective branching factor and n is the number of records. The practical cost is dominated by page reads, writes, and cache misses rather than pointer comparisons alone. A B+ tree stores records or record references in leaves; internal nodes store separator keys and child pointers. Leaves are linked in sorted order, making range scans efficient. B+ trees are standard for database indexes and file systems because they combine high fan-out, page alignment, predictable height, and sequential leaf traversal. | Structure | Main strength | Main limitation |
|---|
| AVL | Very short search paths | More update rebalancing | | Red-black | Robust general-purpose ordered map | More complex invariants | | Splay | Adapts to locality | No per-operation worst-case bound | | Interval tree | Dynamic interval overlap | Specialized augmentation | | Segment tree | Rich range queries/updates | More memory and code | | Fenwick tree | Compact additive prefix operations | Narrower operation model | | B+ tree | External-memory indexing and scans | Page management complexity | | Persistent tree | Historical versions | Extra space and indirection |
10. Persistent TreesA persistent data structure preserves access to previous versions after an update. In a path-copying persistent BST, an update copies every node on the search path and reuses untouched subtrees. If the tree height is h, one update creates O(h) new nodes while retaining the old root as a version pointer. For a balanced persistent tree, lookup is O(log n), update is O(log n) time and O(log n) additional space, and each version is represented by a root reference. Structural sharing avoids copying the entire tree. Immutability simplifies reasoning, enables snapshot queries, and can support multi-version concurrency control. Persistence may be partial or full. Partial persistence permits updates only to the newest version but queries on old versions. Full persistence permits updates to any version. Confluently persistent structures permit combining versions and are substantially more difficult to implement. Garbage collection or reference counting is necessary when versions become unreachable. Persistent trees also increase pointer count and may reduce cache locality. In a database, persistence in the data-structure sense must not be confused with durability: durable storage additionally requires logging, stable media, recovery protocols, and failure semantics. 11. Worked Example: Choosing a Range-Query StructureSuppose an analytics service stores one million daily sales values and must support point corrections and range-sum reports. A Fenwick tree is appropriate when the only update is “change one position” and the query is a sum. A prefix query uses O(log n), a range sum uses two prefix queries, and memory is O(n). If the service instead requires range additions, such as increasing every value in a date interval, plus range minimum queries, a segment tree with lazy propagation is more suitable. A balanced BST augmented with subtree sums is useful when keys are dynamic, sparse, or noninteger, whereas an array-based structure is preferable for dense fixed indices. The selection is therefore determined not simply by asymptotic complexity but by the algebra of the operation, key domain, update model, memory budget, and locality. 12. Applied Case: Versioned Scheduling ServiceBackgroundConsider an illustrative university scheduling service. It stores room reservations as time intervals, must detect conflicts, supports historical queries, and maintains millions of records on disk. ProblemThe service needs three capabilities: efficient overlap detection for active reservations, historical views after corrections, and durable indexing for large data volumes. AnalysisAn interval tree supports overlap queries in memory, but a purely in-memory structure is insufficient for durable, page-oriented storage. A B+ tree is appropriate for persistent primary indexing by room and start time. Historical snapshots require versioned roots or database-level multi-version mechanisms. ApproachThe system uses a B+ tree as the durable ordered index. For each room, an in-memory augmented interval tree is built for the active working set. Each accepted schedule change creates a new logical version: path copying is used for a compact immutable reservation index, while unchanged subtrees are shared. A validation query checks whether the proposed interval overlaps an existing interval using the interval-tree maxHigh field. OutcomeActive conflict checks remain logarithmic in the in-memory index, range scans use linked B+ tree leaves, and administrators can query earlier schedule versions. The design separates concerns: B+ trees address storage locality, interval augmentation addresses overlap semantics, and persistence addresses historical visibility. Learning PointsNo single tree is optimal for every requirement. Combining structures is often superior to forcing one structure to provide storage, interval, and versioning behavior simultaneously. The design must also define time boundaries, transaction isolation, crash recovery, and retention of old versions. 13. Design, Governance, and Contemporary ConsiderationsCorrectness begins with explicit conventions: duplicate-key policy, interval endpoint semantics, index origin for Fenwick trees, page occupancy rules, and version-retention policy. Testing should include sorted insertions, repeated deletions, duplicate keys, empty ranges, boundary intervals, and adversarial update sequences. In production, engineers should instrument height, rotation counts, cache misses, page reads, write amplification, memory overhead, and query latency distributions. Worst-case asymptotic complexity does not predict all practical behavior: cache locality can make Fenwick trees fast, while pointer-heavy persistent trees may be slower despite identical big-O bounds. Concurrency introduces additional concerns. Rotations require synchronization, B+ tree splits need safe latch protocols, and persistent snapshots require well-defined visibility rules. Historical data may contain personal or sensitive information; retention, access control, deletion requirements, and auditability must be addressed. Immutable versions can improve audit trails but can also preserve data longer than intended. Modern systems increasingly combine tree indexes with learned models, columnar storage, compressed keys, and distributed consensus. A learned index may predict positions in a mostly static distribution, but it does not automatically replace a tree's exact ordering and update guarantees. Hybrid designs should be evaluated empirically and must retain a correctness-preserving fallback. Best-Practice Selection Framework- Use AVL when strict worst-case search performance and frequent lookups dominate.
- Use red-black trees for general-purpose mutable ordered maps.
- Use splay trees when access locality is strong and occasional long operations are acceptable.
- Use interval trees for dynamic overlap queries on intervals.
- Use segment trees for rich range aggregation or range updates over indexed domains.
- Use Fenwick trees for compact additive prefix/range operations.
- Use B+ trees for disk, SSD, database, and file-system indexes.
- Use persistent trees when snapshots, rollback, temporal queries, or immutable APIs are central.
- Benchmark realistic workloads, including memory hierarchy and storage behavior.
- Treat invariants and boundary conventions as part of the interface contract.
Chapter SummaryBalanced trees preserve logarithmic height through structural invariants. AVL trees enforce tight height balance, while red-black trees trade a little height for flexible updates and widespread general-purpose use. Splay trees provide amortized efficiency and adapt to locality without strict per-operation guarantees. Augmentation extends a search tree with locally maintainable metadata. Interval trees use subtree maximum endpoints to find overlaps. Segment trees decompose indexed ranges and can support lazy range updates. Fenwick trees provide compact, cache-friendly prefix aggregation for restricted update/query models. B-trees and B+ trees are designed around pages and external-memory costs; B+ trees are particularly effective for ordered range scans. Persistent trees preserve versions through path copying and structural sharing, but incur additional memory, indirection, and lifecycle management. Effective engineering requires matching the invariant, operation algebra, storage medium, workload, concurrency model, and governance requirements to the selected structure. Key TermsBalanced tree: A tree whose height is controlled by structural rules. Binary search tree: A binary tree maintaining an ordered relationship between keys. Balance factor: The difference between left and right subtree heights. Rotation: A local restructuring that preserves in-order key order. AVL tree: A BST with balance factor −1, 0, or 1 at every node. Red-black tree: A colored BST satisfying red-black height and adjacency invariants. Splay tree: A self-adjusting BST that moves accessed nodes toward the root. Amortized analysis: Analysis of average cost over a sequence of operations. Augmentation: Additional node metadata maintained to support specialized queries. Interval tree: An augmented BST for interval-overlap queries. Segment tree: A hierarchical decomposition of an indexed range. Lazy propagation: Deferral of range updates in a segment tree. Fenwick tree: A compact structure for prefix aggregates and point updates. B-tree: A balanced multiway search tree designed for block storage. B+ tree: A B-tree variant whose records are stored in linked leaves. Persistence: Preservation of access to previous data-structure versions. Path copying: Creating new nodes only along an update path. Structural sharing: Reusing unchanged subtrees between versions. Black height: The number of black nodes on a red-black path to a null leaf. Review QuestionsShort Answer Questions- Why does tree height determine the asymptotic cost of BST search?
- State the AVL balance-factor invariant.
- What problem does the maxHigh field solve in an interval tree?
- Distinguish a Fenwick tree from a segment tree.
- What is structural sharing in a persistent tree?
Long Answer Questions- Explain AVL insertion and deletion, including the four rotation configurations.
- Describe red-black invariants and explain why they imply logarithmic height.
- Compare AVL, red-black, and splay trees for a mutable ordered map.
- Explain segment-tree lazy propagation and the conditions required for correct tag composition.
- Explain why B+ trees are preferred for database range indexes.
Analytical / Application Questions- A system needs point updates and range sums over dense integer positions. Which structure should be selected, and why might a segment tree be unnecessary?
- Design a structure for dynamic room-reservation overlap checks with historical snapshots. Identify the roles of interval augmentation, persistence, and B+ storage.
- A workload repeatedly accesses a small hot subset of keys but occasionally requires predictable latency. Compare splay and red-black trees and justify a choice.
Multiple Choice Questions with AnswersQuestion 1Which invariant is required in an AVL tree? A. Every path has the same number of red nodes B. Each node has balance factor between −1 and 1 C. All records occur only in leaves D. Every node has exactly two children Correct Answer: B. Each node has balance factor between −1 and 1 Question 2Which operation is primarily supported by the maxHigh augmentation in an interval tree? A. Finding an overlapping interval B. Sorting all keys externally C. Computing matrix multiplication D. Compressing duplicate records Correct Answer: A. Finding an overlapping interval Question 3What is the usual worst-case time for a Fenwick-tree point update? A. O(1) B. O(log n) C. O(n log n) D. O(n²) Correct Answer: B. O(log n) Question 4Which structure is most directly optimized for page-oriented database storage? A. Splay tree B. AVL tree C. B+ tree D. Fenwick tree Correct Answer: C. B+ tree Question 5What is the principal performance guarantee of a splay tree? A. Every operation is O(1) B. Every operation is worst-case O(log n) C. A sequence of operations has amortized O(log n) cost per operation D. It never performs rotations Correct Answer: C. A sequence of operations has amortized O(log n) cost per operation Question 6In a persistent path-copying tree, which nodes are normally copied during an update? A. Every node in every version B. Only nodes on the update path C. Only leaf nodes, regardless of the path D. No nodes; all updates mutate the old version Correct Answer: B. Only nodes on the update path Question 7For closed intervals [a, b] and [c, d], which condition expresses overlap? A. a > d or c > b B. a ≤ d and c ≤ b C. a + b = c + d D. b < a and d < c Correct Answer: B. a ≤ d and c ≤ b Question 8Which feature most distinguishes a B+ tree from a typical B-tree implementation? A. It cannot store sorted keys B. Its leaves can be linked for efficient range scans C. It requires every internal node to have two children D. It has no balancing procedure Correct Answer: B. Its leaves can be linked for efficient range scans Question 9What does lazy propagation primarily reduce in a segment tree? A. The need to store keys B. The number of nodes visited immediately for range updates C. The height of every binary search tree D. The number of versions retained Correct Answer: B. The number of nodes visited immediately for range updates Question 10If a balanced persistent tree has height O(log n), what additional space does one path-copying update use? A. O(1) B. O(log n) C. O(n²) D. O(2ⁿ) Correct Answer: B. O(log n)
|