12 - Dynamic Structures
Published online by Cambridge University Press: 05 September 2016
Summary
Throughout the book we have assumed that our compact data structures are static, that is, we build them once and they do not change anymore; we only support queries on them. In many cases the data are indeed static or change infrequently enough to allow us afford a periodic reconstruction of the data structures from scratch. In other cases, however, the data change frequently and reconstruction is unfeasible. This is the scenario we address in this chapter.
In many data types, supporting updates together with queries is intrinsically harder than the static case. For example, though we have seen that static bitvectors (Chapter 4), sequences (Chapter 6), and trees (Chapter 8) can support many operations in timeO(log log n) or less, those operations require at least time(log n/ log log n)when insertions and deletions of symbols (for bitvectors and sequences) or nodes (for trees) are allowed. In this chapter we will see practical techniques to turn those structures dynamic, with slowdown factors of typically O(w) compared to the base static representation. When n is large, O(w) becomes similar to O(log n).
Dynamism usually allows one to build the data structures within their final compressed space, by successively inserting the elements. In general, however, this construction is significantly slower than the procedures we have seen throughout the book, although the latter typically use more space.
Bitvectors
Consider a bitvector B[1, n], where in addition to the access, rank, and select operations described in Chapter 4, we support the following updates to B:
insert(B, i, b): inserts bit b between B[i − 1] and B[i], for 1 ≤ i ≤ n + 1.
delete(B, i): deletes B[i], for 1 ≤ i ≤ n.
We show how to support both the query and the update operations in time O(w) while using n + O(n/w) bits of space, where n is the size of B at the time the operation is carried out. We later consider compression.
The data structure is a classical, pointer-based, balanced search tree T (an AVL or a Red-Black tree, for example), where the leaves point to arrays of bits (these bit arrays have no further structure). Each internal node v contains two fields: v.num and v.ones are the total number of bits and of 1s, respectively, stored at the leaves that descend from the left child of v.
- Type
- Chapter
- Information
- Compact Data StructuresA Practical Approach, pp. 450 - 500Publisher: Cambridge University PressPrint publication year: 2016