i2bplustree
Version:
A package to implement the Improved Interval B+ tree, in TypeScript
138 lines (122 loc) • 4.92 kB
text/typescript
import { IBplusInternalNode, Interval, FlatInterval } from './internal';
/**
* Class implementation of a Interval B+-Tree.
* This is the class the user will be importing and using, so it works as an user interface for the IB+-tree
*
* Based on Article: https://pdfs.semanticscholar.org/1343/91e2537a8a9db15a1b5cce2ef66aa3352506.pdf
* B+tree where each node is augmented with the same kind of information as in the binary Interval-trees.
*/
export class IBplusTree<T extends FlatInterval> {
private root: IBplusInternalNode<T>;
/**
* IBplusTree Constructor.
* Alpha is a parameter (0 < alpha < 1) which can be tuned to adjust space(hence update cost)/query_time tradeoff.
* Higher values will lead to fewer splits and hence less storage expansion, but also to worse query efficiency.
* Smaller values will lead to better query efficiency, but increase storage requirements and update costs (due to
* reinsertion of split parts).
*
* @param order The tree's maximum number of children per node.
* @param alpha If alpha is inferior to 0 time splits are not used, and otherwise they are (see consideration regarding
* alpha above).
*/
constructor(order: number, private alpha: number = 0) {
if (order < 2)
throw new Error('IB+ tree must have order >= 2');
if (alpha >= 1)
throw new Error('Alpha can either be negative or a value belonging to ]0, 1[');
this.root = new IBplusInternalNode<T>(order);
}
/**
* Insert the given Interval in the tree
*
* @param int The interval to be inserted
*/
insert(int: T): void {
this.root.insert(int, this.alpha);
while (!this.root.isRoot())
this.root = this.root.getParent();
}
/**
* Delete the given Interval from the tree
*
* @param int The Interval to be removed
*/
delete(int: T): void {
this.root.delete(int, this.alpha);
if (this.root.isChildNewRoot())
// It is forcibly of type IBPlusInternalNode
this.root = <IBplusInternalNode<T>>this.root.getChildren()[0];
}
/**
* Destroy all intervals stored in the tree that are fully
* contained in the given bounds.
*
* @param lowerBound The range query lower bound
* @param upperBound The range query upper bound
*/
rangeDelete(lowerBound: number, upperBound: number): void {
this.root.rangeDelete(lowerBound, upperBound);
while (this.root.isChildNewRoot())
// It is forcibly of type IBPlusInternalNode
this.root = <IBplusInternalNode<T>>this.root.getChildren()[0];
}
/**
* Verify if the given interval exists in the tree.
*
* @param interval the interval to be searched
* @returns the object if exists, null otherwise.
*/
exists(interval: T): boolean {
return this.root.exists(interval);
}
/**
* Get all intervals stored in the tree with equal bounds to the given ones.
*
* @param lowerBound The interval query lower bound
* @param upperBound The interval query upper bound
* @returns Array of found intervals.
*/
search(lowerBound: number, upperBound: number): Set<T> {
return this.root.search(new FlatInterval(lowerBound, upperBound));
}
/**
* Gets the Interval with the lowest bound that intersects the
* given interval.
*
* @param lowerBound The interval query lower bound
* @param upperBound The interval query upper bound
* @returns the FlatInterval that was found, null if none intersected.
*/
loneRangeSearch(lowerBound: number, upperBound: number): T | null {
return this.root.loneRangeSearch(new FlatInterval(lowerBound, upperBound));
}
/**
* Find all intervals stored in the tree that intersect the given range.
*
* @param lowerBound The range query lower bound
* @param upperBound The range query upper bound
* @returns Set of intervals that intersect the range
*/
allRangeSearch(lowerBound: number, upperBound: number): Set<T> {
return this.root.allRangeSearch(new FlatInterval(lowerBound, upperBound));
}
/**
* Find all intervals stored in the tree that are contained in the given range.
*
* @param lowerBound The range query lower bound
* @param upperBound The range query upper bound
* @returns Set of intervals that are contained in the range
*/
containedRangeSearch(lowerBound: number, upperBound: number): Set<T> {
return this.root.containedRangeSearch(new FlatInterval(lowerBound, upperBound));
}
/**
* Represents the current tree as a string.
* Useful for printing purposes.
*
* @returns the root as a string
*/
asString(): string {
return this.root.asString();
}
}