Fusion tree
In computer science, a fusion tree is a type of tree data structure that implements an associative array on -bit integers. When operating on a collection of key–value pairs, it uses space and performs searches in time, which is asymptotically faster than a traditional self-balancing binary search tree, and also better than the van Emde Boas tree for large values of . It achieves this speed by exploiting certain constant-time operations that can be done on a machine word. Fusion trees were invented in 1990 by Michael Fredman and Dan Willard.
Several advances have been made since Fredman and Willard's original 1990 paper. In 1999 it was shown how to implement fusion trees under a model of computation in which all of the underlying operations of the algorithm belong to AC0, a model of circuit complexity that allows addition and bitwise Boolean operations but disallows the multiplication operations used in the original fusion tree algorithm. A dynamic version of fusion trees using hash tables was proposed in 1996 which matched the original structure's runtime in expectation. Another dynamic version using exponential tree was proposed in 2007 which yields worst-case runtimes of per operation. It remains open whether dynamic fusion trees can achieve per operation with high probability.
How it works
A fusion tree is essentially a B-tree with branching factor of , which gives it a height of. To achieve the desired runtimes for updates and queries, the fusion tree must be able to search a node containing up to keys in constant time. This is done by compressing the keys so that all can fit into one machine word, which in turn allows comparisons to be done in parallel.Sketching
Sketching is the method by which each -bit key at a node containing keys is compressed into only bits. Each key may be thought of as a path in the full binary tree of height starting at the root and ending at the leaf corresponding to. To distinguish two paths, it suffices to look at their branching point. All paths together have branching points, so at most bits are needed to distinguish any two of the keys.An important property of the sketch function is that it preserves the order of the keys. That is, for any two keys.
Approximating the sketch
If the locations of the sketch bits are b1 < b2 < ··· < br, then the sketch of the key xw-1···x1x0 is the r-bit integer.With only standard word operations, such as those of the C programming language, it is difficult to directly compute the sketch of a key in constant time. Instead, the sketch bits can be packed into a range of size at most r4, using bitwise AND and multiplication. The bitwise AND operation serves to clear all non-sketch bits from the key, while the multiplication shifts the sketch bits into a small range. Like the "perfect" sketch, the approximate sketch preserves the order of the keys.
Some preprocessing is needed to determine the correct multiplication constant. Each sketch bit in location bi will get shifted to bi + mi via a multiplication by m = 2mi. For the approximate sketch to work, the following three properties must hold:
- bi + mj are distinct for all pairs. This will ensure that the sketch bits are uncorrupted by the multiplication.
- bi + mi is a strictly increasing function of i. That is, the order of the sketch bits is preserved.
- - ≤ r4. That is, the sketch bits are packed into a range of size at most r4.
The approximate sketch is thus computed as follows:
- Mask out all but the sketch bits with a bitwise AND.
- Multiply the key by the predetermined constant m. This operation actually requires two machine words, but this can still by done in constant time.
- Mask out all but the shifted sketch bits. These are now contained in a contiguous block of at most r4 < w4/5 bits.
Parallel comparison
We can assume that the sketch function uses exactly b ≤ r4 bits. Then each block uses 1 + b ≤ w4/5 bits, and since k ≤ w1/5, the total number of bits in the node sketch is at most w.
A brief notational aside: for a bit string s and nonnegative integer m, let sm denote the concatenation of s to itself m times. If t is also a bit string st denotes the concatenation of t to s.
The node sketch makes it possible to search the keys for any b-bit integer y. Let z = k, which can be computed in constant time. Note that 1
sketch
- 0y is always positive, but preserves its leading 1 iff sketch
≥ y. We can thus compute the smallest index i such that sketch
≥ y as follows:- Subtract z from the node sketch.
- Take the bitwise AND of the difference and the constant k. This clears all but the leading bit of each block.
- Find the most significant bit of the result.
- Compute i, using the fact that the leading bit of the i-th block has index i.
Desketching
Unfortunately, the sketch function is not in general order-preserving outside the set of keys, so it is not necessarily the case that xi-1 ≤ q ≤ xi. What is true is that, among all of the keys, either xi-1 or xi has the longest common prefix with q. This is because any key y with a longer common prefix with q would also have more sketch bits in common with q, and thus
sketch
would be closer to sketch
than any sketch
.The length longest common prefix between two w-bit integers a and b can be computed in constant time by finding the most significant bit of the bitwise XOR between a and b. This can then be used to mask out all but the longest common prefix.
Note that p identifies exactly where q branches off from the set of keys. If the next bit of q is 0, then the successor of q is contained in the p1 subtree, and if the next bit of q is 1, then the predecessor of q is contained in the p0 subtree. This suggests the following algorithm:
- Use parallel comparison to find the index i such that
sketch
≤sketch
≤sketch
. - Compute the longest common prefix p of q and either xi-1 or xi.
- Let l-1 be the length of the longest common prefix p.
- # If the l-th bit of q is 0, let e = p10w-l. Use parallel comparison to search for the successor of
sketch
. This is the actual predecessor of q. - # If the l-th bit of q is 1, let e = p01w-l. Use parallel comparison to search for the predecessor of
sketch
. This is the actual successor of q. - Once either the predecessor or successor of q is found, the exact position of q among the set of keys is determined.
Fusion hashing
In hash chaining, in a hash table with a constant load factor, the average size of a chain is constant, but additionally with high probability all chains have size, where is the number of hashed items.
This chain size is small enough that a fusion tree can handle searches and updates within it in constant time per operation. Therefore, the time for all operations in the data structure is constant with high probability.
More precisely, with this data structure, for every inverse-quasipolynomial probability, there is a constant such that the probability that there exists an operation that exceeds time is at most.