SegmentQuery
Eonil, 2019.
Dynamically stores additive values and get arbitrary sub-range sums in O(log(n)) time.
This is an implementation of something called "segment-tree" or "interval-tree". You insert/remove lengths of consecutive segments and query positions on it. I'm not sure which one is correct name.
How to Use
Add dependency.
.package(url: "https://github.com/eonil/swift-segment-query", .branch("master")),
And use.
import SegmentQuery
var x = SegmentQuery<Int>()
/// Append segment lengths.
x.append(contentsOf: [111,222,333])
/// Get subrange sum.
let s = x[1..<3].sum
assert(s == 222+333)
/// Get start/end offsets of a segment 1.
let a = x[..<1].sum
let b = x[...1].sum
let c = a..<b
/// Get index of segment and in-segment-offset from an offset.
let (a,b) = x.location(at: 230)
assert(a == 1)
assert(b == 8)
Requirements
- Swift 5.x.
 - Swift Package Manager.
 
Complexity
- O(log(n)) for element query/insert/update/remove and sub-sum query.
 
Performance
I couldn't find other segment query library written in Swift for comparison. Instead, I performed insert/remove performance comparison with well-known B-Tree library written by Lőrentey. This is one-by-one random Int number insert/remove at random location on 64-bit macOS,
With list of 128K values,
- 4x faster than 
Swift.Array. - Very close speed to 
BTree.List. 
With list of 1 million values,
- 4x faster than 
BTree.List. 
Run SegmentQueryBenchmark to get numbers on your machine.
Implementation
- B-Tree based with no key stored.
 - Only values are stored.
 - Values are stored only on leafs.
 - Buffer sizes are optimized for ordered list behavior with dynamic automatic sum.
 
Missing Features
- Balancing after remove. (Now only insertion is balanced by B-Tree insertion algorithm)
 - Bulk insert/remove implementation.
 - Sequential element iteration in O(n) time. Now it's O(n log n).
 - Sub-sum indexing in each node. We can store sub-sum for each branch/leaf node children to perform binary search to get an item. There is a trade-off, but I didn't try due to lack of time.
 
Credit & License
Copyright(C) Eonil 2019. All rights reserved. Using of this code is licensed under "MIT License".