Basic implementation of segment tree in Go
Read more about segment tree: https://en.wikipedia.org/wiki/Segment_tree
All operations (see below) are O(log(n))
where n
is the size of the array on which queries are performed.
package main
import "github.com/ideahitme/segment"
func main() {
tree, err := segment.NewTree([]int{1,2,3,4,5}, segment.MinFunc{})
if err != nil {
//handle error, only happens when empty slice is passed
}
// minimum value in range [0:4]
fmt.Println(tree.RQ(0, 4)) // 1, <nil>
// increase values in range [1:4] by -5
err := tree.Add(-5, 1, 4)
if err != nil {
//handle error, only happens when ranges are incorrect
}
// so now we have array of [1, -3, -2, -1, 0]
fmt.Println(tree.RQ(0, 2)) // -3, <nil>
}
NOTE: Slice passed to the tree is internally copied, therefore can be safely modified
import "github.com/ideahitme/segment"
...
// supports range minimum queries
minTree, _ := segment.NewTree([]int{124,123, 1, -10000, 412}, segment.MinFunc{})
// supports range maximum queries
maxTree, _ := segment.NewTree([]int{124,123, 1, -10000, 412}, segment.MaxFunc{})
x := []int{1, 20, 3, 40, 5, 60, 7, -100} // our original array
tree, _ := segment.NewTree(x, segment.MaxFunc{}) // segment tree which supports Range Maximum Queries
fmt.Println(tree.RQ(0, 0))
fmt.Println(tree.RQ(0, 3))
fmt.Println(tree.RQ(3, 5))
fmt.Println(tree.RQ(6, 7))
fmt.Println(tree.RQ(7, 7))
//Output:
//1 <nil>
//40 <nil>
//60 <nil>
//7 <nil>
//-100 <nil>
x := []int{1, 20, 3, 40, 5, 60, 7, -100} // our original array
tree, _ := segment.NewTree(x, segment.MaxFunc{}) // segment tree which supports Range Maximum Queries
fmt.Println(tree.RQ(0, 3))
tree.Add(5, 2, 4) //increase elements in [2:4] by 5
fmt.Println(tree.RQ(2, 4))
tree.Add(13, 2, 2) // increase element at 2 by 13
fmt.Println(tree.RQ(0, 2))
tree.Add(10000, 0, 7) // increase all by 10000
fmt.Println(tree.RQ(0, 7))
//Output:
//40 <nil>
//45 <nil>
//21 <nil>
//10060 <nil>
More functionalities and their examples coming soon...
Naive approach vs Segment Tree
BenchmarkNaive2-4 5000 370691 ns/op
BenchmarkNaive100-4 2000 959208 ns/op
BenchmarkNaive10000-4 20 90091228 ns/op
BenchmarkNaive100000-4 1 1003322923 ns/op
BenchmarkTree2-4 2000 828003 ns/op
BenchmarkTree100-4 300 4318972 ns/op
BenchmarkTree10000-4 100 12195815 ns/op
BenchmarkTree100000-4 100 15319705 ns/op
- Make it work for other types, at least in64 and float64
- More/better Benchmarks