Experimenting with implementing an immutable interval tree in Moonbit
moon add kesmeey/immut_IntervalTree// An empty interval tree - O(1)
let tree : T[Int, String] = @immut_IntervalTree.new()
// With a single interval - O(1)
let interval = Interval::{ low: 10, high: 20 }
let single_tree = @immut_IntervalTree.singleton(interval, "data")
// From an array of intervals - O(n log n)
let intervals = [
(Interval::{ low: 10, high: 20 }, "A"),
(Interval::{ low: 15, high: 25 }, "B"),
(Interval::{ low: 5, high: 15 }, "C"),
]
let tree_from_array = @immut_IntervalTree.from_array(intervals)// Empty tree
let tree : T[Int, String] = @immut_IntervalTree.new()
// Insert interval, returns a new tree - O(log n)
let tree2 = tree.insert(Interval::{ low: 10, high: 20 }, "A")
// Original tree remains unchanged
assert_eq!(tree.size, 0)
assert_eq!(tree2.size, 1)// Create new tree and add data
let tree = @immut_IntervalTree.new()
.insert(Interval::{ low: 10, high: 20 }, "A")
.insert(Interval::{ low: 15, high: 25 }, "B")
.insert(Interval::{ low: 5, high: 15 }, "C")
// Exact match lookup - O(log n)
let data = tree.find_exact(Interval::{ low: 10, high: 20 })
assert_eq!(data, Some("A"))
// Find overlapping intervals - O(k + log n) where k is the number of results
let overlaps = tree.find_overlaps(Interval::{ low: 12, high: 18 })// Create tree and add data
let tree = @immut_IntervalTree.new()
.insert(Interval::{ low: 10, high: 20 }, "A")
.insert(Interval::{ low: 15, high: 25 }, "B")
// Remove an interval, returns a new tree - O(log n)
let tree2 = tree.remove(Interval::{ low: 10, high: 20 })
assert_eq!(tree2.size, 1)
assert_eq!(tree2.find_exact(Interval::{ low: 10, high: 20 }), None)
// Original tree remains unchanged
assert_eq!(tree.size, 2)
assert_eq!(tree.find_exact(Interval::{ low: 10, high: 20 }), Some("A"))// Create tree and add data
let tree = @immut_IntervalTree.new().insert(
Interval::{ low: 10, high: 20 },
"A",
)
// Replace data, returns a new tree - O(log n)
let tree2 = tree.replace_exact(Interval::{ low: 10, high: 20 }, "Updated A")
// Verify update
assert_eq!(tree.find_exact(Interval::{ low: 10, high: 20 }), Some("A"))
assert_eq!(
tree2.find_exact(Interval::{ low: 10, high: 20 }),
Some("Updated A"),
)// Create tree and add data
let tree = @immut_IntervalTree.new()
.insert(Interval::{ low: 10, high: 20 }, "A")
.insert(Interval::{ low: 15, high: 25 }, "B")
// Clear the tree, returns a new empty tree - O(1)
let empty_tree = tree.clear()
assert_eq!(empty_tree.size, 0)
assert_eq!(empty_tree.root, None)
// Original tree remains unchanged
assert_eq!(tree.size, 2)// Create tree and add data
let tree = @immut_IntervalTree.new()
.insert(Interval::{ low: 10, high: 20 }, "A")
.insert(Interval::{ low: 15, high: 25 }, "B")
// Find intervals contained within a range - O(n) in worst case
let contained = tree.find_contained(Interval::{ low: 0, high: 30 })
// Check if a specific interval exists - O(log n)
let exists = tree.contains(Interval::{ low: 10, high: 20 })
// Convert all intervals to an array - O(n)
let all_intervals = tree.to_array()// Float type intervals
let float_tree = @immut_IntervalTree.new()
.insert(Interval::{ low: 10.5, high: 20.5 }, "A")
// String type intervals
let string_tree = @immut_IntervalTree.new()
.insert(Interval::{ low: "a", high: "z" }, 1)// Build tree using method chaining
let tree = @immut_IntervalTree.new()
.insert(Interval::{ low: 10, high: 20 }, "A")
.insert(Interval::{ low: 15, high: 25 }, "B")
.insert(Interval::{ low: 5, high: 15 }, "C")
// Combine query, modification, and removal operations
let result = tree
.replace_exact(Interval::{ low: 10, high: 20 }, "Updated A")
.remove(Interval::{ low: 15, high: 25 })
// Original tree unchanged, result contains all changes
assert_eq!(tree.size, 3)
assert_eq!(result.size, 2)| Operation | Time Complexity | Description |
|---|---|---|
| new() | O(1) | Create an empty tree |
| singleton() | O(1) | Create a tree with one interval |
| from_array() | O(n log n) | Create from array of intervals |
| insert() | O(log n) | Insert a new interval |
| remove() | O(log n) | Remove an interval |
| replace_exact() | O(log n) | Replace data for an interval |
| find_exact() | O(log n) | Find an exact interval match |
| find_overlaps() | O(k + log n) | Find overlapping intervals (k = result count) |
| find_contained() | O(n) | Find intervals contained within a range |
| contains() | O(log n) | Check if an interval exists |
| to_array() | O(n) | Convert tree to array |
| clear() | O(1) | Clear all intervals |
pub(all) struct Interval[T] {
low : T
high : T
}impl Eq for IntervalMatch[T, D]impl Show for IntervalMatch[T, D]impl Eq for IntervalOptionsimpl Show for IntervalOptionspub(all) enum IntervalType {
Closed
Open
LeftClosed
RightClosed
}impl Eq for IntervalTypeimpl Show for IntervalTypefn[V : Compare + Eq, D] insert_node_immut(node : Node[V, D], new_node : Node[V, D], allow_duplicates~ : Bool = ..) -> InsertResult[V, D]fn[V : Compare + Eq] interval_contains(a : Interval[V], b : Interval[V], interval_type~ : IntervalType = ..) -> Boolfn[V : Compare + Eq] intervals_overlap(a : Interval[V], b : Interval[V], interval_type~ : IntervalType = ..) -> Boolfn[V : Compare + Eq, D] remove_node_immut(node : Node[V, D], interval : Interval[V]) -> RemoveResult[V, D]fn[V : Compare + Eq, D] singleton(interval : Interval[V], data : D, options~ : IntervalOptions = ..) -> T[V, D]Install
Download zipExperimenting with implementing an immutable interval tree in Moonbit