1213 lines
28 KiB
Go
1213 lines
28 KiB
Go
// Copyright 2020 Joshua J Baker. All rights reserved.
|
|
// Use of this source code is governed by an MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
package btree
|
|
|
|
import "sync/atomic"
|
|
|
|
type ordered interface {
|
|
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
|
|
~float32 | ~float64 | ~string
|
|
}
|
|
|
|
type copier[T any] interface {
|
|
Copy() T
|
|
}
|
|
|
|
type isoCopier[T any] interface {
|
|
IsoCopy() T
|
|
}
|
|
|
|
func degreeToMinMax(deg int) (min, max int) {
|
|
if deg <= 0 {
|
|
deg = 32
|
|
} else if deg == 1 {
|
|
deg = 2 // must have at least 2
|
|
}
|
|
max = deg*2 - 1 // max items per node. max children is +1
|
|
min = max / 2
|
|
return min, max
|
|
}
|
|
|
|
var gisoid uint64
|
|
|
|
func newIsoID() uint64 {
|
|
return atomic.AddUint64(&gisoid, 1)
|
|
}
|
|
|
|
type mapPair[K ordered, V any] struct {
|
|
// The `value` field should be before the `key` field because doing so
|
|
// allows for the Go compiler to optimize away the `value` field when
|
|
// it's a `struct{}`, which is the case for `btree.Set`.
|
|
value V
|
|
key K
|
|
}
|
|
|
|
type Map[K ordered, V any] struct {
|
|
isoid uint64
|
|
root *mapNode[K, V]
|
|
count int
|
|
empty mapPair[K, V]
|
|
min int // min items
|
|
max int // max items
|
|
copyValues bool
|
|
isoCopyValues bool
|
|
}
|
|
|
|
func NewMap[K ordered, V any](degree int) *Map[K, V] {
|
|
m := new(Map[K, V])
|
|
m.init(degree)
|
|
return m
|
|
}
|
|
|
|
type mapNode[K ordered, V any] struct {
|
|
isoid uint64
|
|
count int
|
|
items []mapPair[K, V]
|
|
children *[]*mapNode[K, V]
|
|
}
|
|
|
|
// Copy the node for safe isolation.
|
|
func (tr *Map[K, V]) copy(n *mapNode[K, V]) *mapNode[K, V] {
|
|
n2 := new(mapNode[K, V])
|
|
n2.isoid = tr.isoid
|
|
n2.count = n.count
|
|
n2.items = make([]mapPair[K, V], len(n.items), cap(n.items))
|
|
copy(n2.items, n.items)
|
|
if tr.copyValues {
|
|
for i := 0; i < len(n2.items); i++ {
|
|
n2.items[i].value =
|
|
((interface{})(n2.items[i].value)).(copier[V]).Copy()
|
|
}
|
|
} else if tr.isoCopyValues {
|
|
for i := 0; i < len(n2.items); i++ {
|
|
n2.items[i].value =
|
|
((interface{})(n2.items[i].value)).(isoCopier[V]).IsoCopy()
|
|
}
|
|
}
|
|
if !n.leaf() {
|
|
n2.children = new([]*mapNode[K, V])
|
|
*n2.children = make([]*mapNode[K, V], len(*n.children), tr.max+1)
|
|
copy(*n2.children, *n.children)
|
|
}
|
|
return n2
|
|
}
|
|
|
|
// isoLoad loads the provided node and, if needed, performs a copy-on-write.
|
|
func (tr *Map[K, V]) isoLoad(cn **mapNode[K, V], mut bool) *mapNode[K, V] {
|
|
if mut && (*cn).isoid != tr.isoid {
|
|
*cn = tr.copy(*cn)
|
|
}
|
|
return *cn
|
|
}
|
|
|
|
func (tr *Map[K, V]) Copy() *Map[K, V] {
|
|
return tr.IsoCopy()
|
|
}
|
|
|
|
func (tr *Map[K, V]) IsoCopy() *Map[K, V] {
|
|
tr2 := new(Map[K, V])
|
|
*tr2 = *tr
|
|
tr2.isoid = newIsoID()
|
|
tr.isoid = newIsoID()
|
|
return tr2
|
|
}
|
|
|
|
func (tr *Map[K, V]) newNode(leaf bool) *mapNode[K, V] {
|
|
n := new(mapNode[K, V])
|
|
n.isoid = tr.isoid
|
|
if !leaf {
|
|
n.children = new([]*mapNode[K, V])
|
|
}
|
|
return n
|
|
}
|
|
|
|
// leaf returns true if the node is a leaf.
|
|
func (n *mapNode[K, V]) leaf() bool {
|
|
return n.children == nil
|
|
}
|
|
|
|
func (tr *Map[K, V]) search(n *mapNode[K, V], key K) (index int, found bool) {
|
|
low, high := 0, len(n.items)
|
|
for low < high {
|
|
h := (low + high) / 2
|
|
if !(key < n.items[h].key) {
|
|
low = h + 1
|
|
} else {
|
|
high = h
|
|
}
|
|
}
|
|
if low > 0 && !(n.items[low-1].key < key) {
|
|
return low - 1, true
|
|
}
|
|
return low, false
|
|
}
|
|
|
|
func (tr *Map[K, V]) init(degree int) {
|
|
if tr.min != 0 {
|
|
return
|
|
}
|
|
tr.min, tr.max = degreeToMinMax(degree)
|
|
_, tr.copyValues = ((interface{})(tr.empty.value)).(copier[V])
|
|
if !tr.copyValues {
|
|
_, tr.isoCopyValues = ((interface{})(tr.empty.value)).(isoCopier[V])
|
|
}
|
|
}
|
|
|
|
// Set or replace a value for a key
|
|
func (tr *Map[K, V]) Set(key K, value V) (V, bool) {
|
|
item := mapPair[K, V]{key: key, value: value}
|
|
if tr.root == nil {
|
|
tr.init(0)
|
|
tr.root = tr.newNode(true)
|
|
tr.root.items = append([]mapPair[K, V]{}, item)
|
|
tr.root.count = 1
|
|
tr.count = 1
|
|
return tr.empty.value, false
|
|
}
|
|
prev, replaced, split := tr.nodeSet(&tr.root, item)
|
|
if split {
|
|
left := tr.root
|
|
right, median := tr.nodeSplit(left)
|
|
tr.root = tr.newNode(false)
|
|
*tr.root.children = make([]*mapNode[K, V], 0, tr.max+1)
|
|
*tr.root.children = append([]*mapNode[K, V]{}, left, right)
|
|
tr.root.items = append([]mapPair[K, V]{}, median)
|
|
tr.root.updateCount()
|
|
return tr.Set(item.key, item.value)
|
|
}
|
|
if replaced {
|
|
return prev, true
|
|
}
|
|
tr.count++
|
|
return tr.empty.value, false
|
|
}
|
|
|
|
func (tr *Map[K, V]) nodeSplit(n *mapNode[K, V],
|
|
) (right *mapNode[K, V], median mapPair[K, V]) {
|
|
i := tr.max / 2
|
|
median = n.items[i]
|
|
|
|
// right node
|
|
right = tr.newNode(n.leaf())
|
|
right.items = n.items[i+1:]
|
|
if !n.leaf() {
|
|
*right.children = (*n.children)[i+1:]
|
|
}
|
|
right.updateCount()
|
|
|
|
// left node
|
|
n.items[i] = tr.empty
|
|
n.items = n.items[:i:i]
|
|
if !n.leaf() {
|
|
*n.children = (*n.children)[: i+1 : i+1]
|
|
}
|
|
n.updateCount()
|
|
return right, median
|
|
}
|
|
|
|
func (n *mapNode[K, V]) updateCount() {
|
|
n.count = len(n.items)
|
|
if !n.leaf() {
|
|
for i := 0; i < len(*n.children); i++ {
|
|
n.count += (*n.children)[i].count
|
|
}
|
|
}
|
|
}
|
|
|
|
func (tr *Map[K, V]) nodeSet(pn **mapNode[K, V], item mapPair[K, V],
|
|
) (prev V, replaced bool, split bool) {
|
|
n := tr.isoLoad(pn, true)
|
|
i, found := tr.search(n, item.key)
|
|
if found {
|
|
prev = n.items[i].value
|
|
n.items[i] = item
|
|
return prev, true, false
|
|
}
|
|
if n.leaf() {
|
|
if len(n.items) == tr.max {
|
|
return tr.empty.value, false, true
|
|
}
|
|
n.items = append(n.items, tr.empty)
|
|
copy(n.items[i+1:], n.items[i:])
|
|
n.items[i] = item
|
|
n.count++
|
|
return tr.empty.value, false, false
|
|
}
|
|
prev, replaced, split = tr.nodeSet(&(*n.children)[i], item)
|
|
if split {
|
|
if len(n.items) == tr.max {
|
|
return tr.empty.value, false, true
|
|
}
|
|
right, median := tr.nodeSplit((*n.children)[i])
|
|
*n.children = append(*n.children, nil)
|
|
copy((*n.children)[i+1:], (*n.children)[i:])
|
|
(*n.children)[i+1] = right
|
|
n.items = append(n.items, tr.empty)
|
|
copy(n.items[i+1:], n.items[i:])
|
|
n.items[i] = median
|
|
return tr.nodeSet(&n, item)
|
|
}
|
|
if !replaced {
|
|
n.count++
|
|
}
|
|
return prev, replaced, false
|
|
}
|
|
|
|
func (tr *Map[K, V]) Scan(iter func(key K, value V) bool) {
|
|
tr.scan(iter, false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) ScanMut(iter func(key K, value V) bool) {
|
|
tr.scan(iter, true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) scan(iter func(key K, value V) bool, mut bool) {
|
|
if tr.root == nil {
|
|
return
|
|
}
|
|
tr.nodeScan(&tr.root, iter, mut)
|
|
}
|
|
|
|
func (tr *Map[K, V]) nodeScan(cn **mapNode[K, V],
|
|
iter func(key K, value V) bool, mut bool,
|
|
) bool {
|
|
n := tr.isoLoad(cn, mut)
|
|
if n.leaf() {
|
|
for i := 0; i < len(n.items); i++ {
|
|
if !iter(n.items[i].key, n.items[i].value) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
for i := 0; i < len(n.items); i++ {
|
|
if !tr.nodeScan(&(*n.children)[i], iter, mut) {
|
|
return false
|
|
}
|
|
if !iter(n.items[i].key, n.items[i].value) {
|
|
return false
|
|
}
|
|
}
|
|
return tr.nodeScan(&(*n.children)[len(*n.children)-1], iter, mut)
|
|
}
|
|
|
|
// Get a value for key.
|
|
func (tr *Map[K, V]) Get(key K) (V, bool) {
|
|
return tr.get(key, false)
|
|
}
|
|
|
|
// GetMut gets a value for key.
|
|
// If needed, this may perform a copy the resulting value before returning.
|
|
//
|
|
// Mut methods are only useful when all of the following are true:
|
|
// - The interior data of the value requires changes.
|
|
// - The value is a pointer type.
|
|
// - The BTree has been copied using `Copy()` or `IsoCopy()`.
|
|
// - The value itself has a `Copy()` or `IsoCopy()` method.
|
|
//
|
|
// Mut methods may modify the tree structure and should have the same
|
|
// considerations as other mutable operations like Set, Delete, Clear, etc.
|
|
func (tr *Map[K, V]) GetMut(key K) (V, bool) {
|
|
return tr.get(key, true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) get(key K, mut bool) (V, bool) {
|
|
if tr.root == nil {
|
|
return tr.empty.value, false
|
|
}
|
|
n := tr.isoLoad(&tr.root, mut)
|
|
for {
|
|
i, found := tr.search(n, key)
|
|
if found {
|
|
return n.items[i].value, true
|
|
}
|
|
if n.leaf() {
|
|
return tr.empty.value, false
|
|
}
|
|
n = tr.isoLoad(&(*n.children)[i], mut)
|
|
}
|
|
}
|
|
|
|
// Len returns the number of items in the tree
|
|
func (tr *Map[K, V]) Len() int {
|
|
return tr.count
|
|
}
|
|
|
|
// Delete a value for a key and returns the deleted value.
|
|
// Returns false if there was no value by that key found.
|
|
func (tr *Map[K, V]) Delete(key K) (V, bool) {
|
|
if tr.root == nil {
|
|
return tr.empty.value, false
|
|
}
|
|
prev, deleted := tr.delete(&tr.root, false, key)
|
|
if !deleted {
|
|
return tr.empty.value, false
|
|
}
|
|
if len(tr.root.items) == 0 && !tr.root.leaf() {
|
|
tr.root = (*tr.root.children)[0]
|
|
}
|
|
tr.count--
|
|
if tr.count == 0 {
|
|
tr.root = nil
|
|
}
|
|
return prev.value, true
|
|
}
|
|
|
|
func (tr *Map[K, V]) delete(pn **mapNode[K, V], max bool, key K,
|
|
) (mapPair[K, V], bool) {
|
|
n := tr.isoLoad(pn, true)
|
|
var i int
|
|
var found bool
|
|
if max {
|
|
i, found = len(n.items)-1, true
|
|
} else {
|
|
i, found = tr.search(n, key)
|
|
}
|
|
if n.leaf() {
|
|
if found {
|
|
// found the items at the leaf, remove it and return.
|
|
prev := n.items[i]
|
|
copy(n.items[i:], n.items[i+1:])
|
|
n.items[len(n.items)-1] = tr.empty
|
|
n.items = n.items[:len(n.items)-1]
|
|
n.count--
|
|
return prev, true
|
|
}
|
|
return tr.empty, false
|
|
}
|
|
|
|
var prev mapPair[K, V]
|
|
var deleted bool
|
|
if found {
|
|
if max {
|
|
i++
|
|
prev, deleted = tr.delete(&(*n.children)[i], true, tr.empty.key)
|
|
} else {
|
|
prev = n.items[i]
|
|
maxItem, _ := tr.delete(&(*n.children)[i], true, tr.empty.key)
|
|
deleted = true
|
|
n.items[i] = maxItem
|
|
}
|
|
} else {
|
|
prev, deleted = tr.delete(&(*n.children)[i], max, key)
|
|
}
|
|
if !deleted {
|
|
return tr.empty, false
|
|
}
|
|
n.count--
|
|
if len((*n.children)[i].items) < tr.min {
|
|
tr.nodeRebalance(n, i)
|
|
}
|
|
return prev, true
|
|
}
|
|
|
|
// nodeRebalance rebalances the child nodes following a delete operation.
|
|
// Provide the index of the child node with the number of items that fell
|
|
// below minItems.
|
|
func (tr *Map[K, V]) nodeRebalance(n *mapNode[K, V], i int) {
|
|
if i == len(n.items) {
|
|
i--
|
|
}
|
|
|
|
// ensure copy-on-write
|
|
left := tr.isoLoad(&(*n.children)[i], true)
|
|
right := tr.isoLoad(&(*n.children)[i+1], true)
|
|
|
|
if len(left.items)+len(right.items) < tr.max {
|
|
// Merges the left and right children nodes together as a single node
|
|
// that includes (left,item,right), and places the contents into the
|
|
// existing left node. Delete the right node altogether and move the
|
|
// following items and child nodes to the left by one slot.
|
|
|
|
// merge (left,item,right)
|
|
left.items = append(left.items, n.items[i])
|
|
left.items = append(left.items, right.items...)
|
|
if !left.leaf() {
|
|
*left.children = append(*left.children, *right.children...)
|
|
}
|
|
left.count += right.count + 1
|
|
|
|
// move the items over one slot
|
|
copy(n.items[i:], n.items[i+1:])
|
|
n.items[len(n.items)-1] = tr.empty
|
|
n.items = n.items[:len(n.items)-1]
|
|
|
|
// move the children over one slot
|
|
copy((*n.children)[i+1:], (*n.children)[i+2:])
|
|
(*n.children)[len(*n.children)-1] = nil
|
|
(*n.children) = (*n.children)[:len(*n.children)-1]
|
|
} else if len(left.items) > len(right.items) {
|
|
// move left -> right over one slot
|
|
|
|
// Move the item of the parent node at index into the right-node first
|
|
// slot, and move the left-node last item into the previously moved
|
|
// parent item slot.
|
|
right.items = append(right.items, tr.empty)
|
|
copy(right.items[1:], right.items)
|
|
right.items[0] = n.items[i]
|
|
right.count++
|
|
n.items[i] = left.items[len(left.items)-1]
|
|
left.items[len(left.items)-1] = tr.empty
|
|
left.items = left.items[:len(left.items)-1]
|
|
left.count--
|
|
|
|
if !left.leaf() {
|
|
// move the left-node last child into the right-node first slot
|
|
*right.children = append(*right.children, nil)
|
|
copy((*right.children)[1:], *right.children)
|
|
(*right.children)[0] = (*left.children)[len(*left.children)-1]
|
|
(*left.children)[len(*left.children)-1] = nil
|
|
(*left.children) = (*left.children)[:len(*left.children)-1]
|
|
left.count -= (*right.children)[0].count
|
|
right.count += (*right.children)[0].count
|
|
}
|
|
} else {
|
|
// move left <- right over one slot
|
|
|
|
// Same as above but the other direction
|
|
left.items = append(left.items, n.items[i])
|
|
left.count++
|
|
n.items[i] = right.items[0]
|
|
copy(right.items, right.items[1:])
|
|
right.items[len(right.items)-1] = tr.empty
|
|
right.items = right.items[:len(right.items)-1]
|
|
right.count--
|
|
|
|
if !left.leaf() {
|
|
*left.children = append(*left.children, (*right.children)[0])
|
|
copy(*right.children, (*right.children)[1:])
|
|
(*right.children)[len(*right.children)-1] = nil
|
|
*right.children = (*right.children)[:len(*right.children)-1]
|
|
left.count += (*left.children)[len(*left.children)-1].count
|
|
right.count -= (*left.children)[len(*left.children)-1].count
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ascend the tree within the range [pivot, last]
|
|
// Pass nil for pivot to scan all item in ascending order
|
|
// Return false to stop iterating
|
|
func (tr *Map[K, V]) Ascend(pivot K, iter func(key K, value V) bool) {
|
|
tr.ascend(pivot, iter, false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) AscendMut(pivot K, iter func(key K, value V) bool) {
|
|
tr.ascend(pivot, iter, true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) ascend(pivot K, iter func(key K, value V) bool, mut bool) {
|
|
if tr.root == nil {
|
|
return
|
|
}
|
|
tr.nodeAscend(&tr.root, pivot, iter, mut)
|
|
}
|
|
|
|
// The return value of this function determines whether we should keep iterating
|
|
// upon this functions return.
|
|
func (tr *Map[K, V]) nodeAscend(cn **mapNode[K, V], pivot K,
|
|
iter func(key K, value V) bool, mut bool,
|
|
) bool {
|
|
n := tr.isoLoad(cn, mut)
|
|
i, found := tr.search(n, pivot)
|
|
if !found {
|
|
if !n.leaf() {
|
|
if !tr.nodeAscend(&(*n.children)[i], pivot, iter, mut) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
// We are either in the case that
|
|
// - node is found, we should iterate through it starting at `i`,
|
|
// the index it was located at.
|
|
// - node is not found, and TODO: fill in.
|
|
for ; i < len(n.items); i++ {
|
|
if !iter(n.items[i].key, n.items[i].value) {
|
|
return false
|
|
}
|
|
if !n.leaf() {
|
|
if !tr.nodeScan(&(*n.children)[i+1], iter, mut) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (tr *Map[K, V]) Reverse(iter func(key K, value V) bool) {
|
|
tr.reverse(iter, false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) ReverseMut(iter func(key K, value V) bool) {
|
|
tr.reverse(iter, true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) reverse(iter func(key K, value V) bool, mut bool) {
|
|
if tr.root == nil {
|
|
return
|
|
}
|
|
tr.nodeReverse(&tr.root, iter, mut)
|
|
}
|
|
|
|
func (tr *Map[K, V]) nodeReverse(cn **mapNode[K, V],
|
|
iter func(key K, value V) bool, mut bool,
|
|
) bool {
|
|
n := tr.isoLoad(cn, mut)
|
|
if n.leaf() {
|
|
for i := len(n.items) - 1; i >= 0; i-- {
|
|
if !iter(n.items[i].key, n.items[i].value) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
if !tr.nodeReverse(&(*n.children)[len(*n.children)-1], iter, mut) {
|
|
return false
|
|
}
|
|
for i := len(n.items) - 1; i >= 0; i-- {
|
|
if !iter(n.items[i].key, n.items[i].value) {
|
|
return false
|
|
}
|
|
if !tr.nodeReverse(&(*n.children)[i], iter, mut) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Descend the tree within the range [pivot, first]
|
|
// Pass nil for pivot to scan all item in descending order
|
|
// Return false to stop iterating
|
|
func (tr *Map[K, V]) Descend(pivot K, iter func(key K, value V) bool) {
|
|
tr.descend(pivot, iter, false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) DescendMut(pivot K, iter func(key K, value V) bool) {
|
|
tr.descend(pivot, iter, true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) descend(
|
|
pivot K,
|
|
iter func(key K, value V) bool,
|
|
mut bool,
|
|
) {
|
|
if tr.root == nil {
|
|
return
|
|
}
|
|
tr.nodeDescend(&tr.root, pivot, iter, mut)
|
|
}
|
|
|
|
func (tr *Map[K, V]) nodeDescend(cn **mapNode[K, V], pivot K,
|
|
iter func(key K, value V) bool, mut bool,
|
|
) bool {
|
|
n := tr.isoLoad(cn, mut)
|
|
i, found := tr.search(n, pivot)
|
|
if !found {
|
|
if !n.leaf() {
|
|
if !tr.nodeDescend(&(*n.children)[i], pivot, iter, mut) {
|
|
return false
|
|
}
|
|
}
|
|
i--
|
|
}
|
|
for ; i >= 0; i-- {
|
|
if !iter(n.items[i].key, n.items[i].value) {
|
|
return false
|
|
}
|
|
if !n.leaf() {
|
|
if !tr.nodeReverse(&(*n.children)[i], iter, mut) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Load is for bulk loading pre-sorted items
|
|
func (tr *Map[K, V]) Load(key K, value V) (V, bool) {
|
|
item := mapPair[K, V]{key: key, value: value}
|
|
if tr.root == nil {
|
|
return tr.Set(item.key, item.value)
|
|
}
|
|
n := tr.isoLoad(&tr.root, true)
|
|
for {
|
|
n.count++ // optimistically update counts
|
|
if n.leaf() {
|
|
if len(n.items) < tr.max {
|
|
if n.items[len(n.items)-1].key < item.key {
|
|
n.items = append(n.items, item)
|
|
tr.count++
|
|
return tr.empty.value, false
|
|
}
|
|
}
|
|
break
|
|
}
|
|
n = tr.isoLoad(&(*n.children)[len(*n.children)-1], true)
|
|
}
|
|
// revert the counts
|
|
n = tr.root
|
|
for {
|
|
n.count--
|
|
if n.leaf() {
|
|
break
|
|
}
|
|
n = (*n.children)[len(*n.children)-1]
|
|
}
|
|
return tr.Set(item.key, item.value)
|
|
}
|
|
|
|
// Min returns the minimum item in tree.
|
|
// Returns nil if the treex has no items.
|
|
func (tr *Map[K, V]) Min() (K, V, bool) {
|
|
return tr.minMut(false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) MinMut() (K, V, bool) {
|
|
return tr.minMut(true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) minMut(mut bool) (key K, value V, ok bool) {
|
|
if tr.root == nil {
|
|
return key, value, false
|
|
}
|
|
n := tr.isoLoad(&tr.root, mut)
|
|
for {
|
|
if n.leaf() {
|
|
item := n.items[0]
|
|
return item.key, item.value, true
|
|
}
|
|
n = tr.isoLoad(&(*n.children)[0], mut)
|
|
}
|
|
}
|
|
|
|
// Max returns the maximum item in tree.
|
|
// Returns nil if the tree has no items.
|
|
func (tr *Map[K, V]) Max() (K, V, bool) {
|
|
return tr.maxMut(false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) MaxMut() (K, V, bool) {
|
|
return tr.maxMut(true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) maxMut(mut bool) (K, V, bool) {
|
|
if tr.root == nil {
|
|
return tr.empty.key, tr.empty.value, false
|
|
}
|
|
n := tr.isoLoad(&tr.root, mut)
|
|
for {
|
|
if n.leaf() {
|
|
item := n.items[len(n.items)-1]
|
|
return item.key, item.value, true
|
|
}
|
|
n = tr.isoLoad(&(*n.children)[len(*n.children)-1], mut)
|
|
}
|
|
}
|
|
|
|
// PopMin removes the minimum item in tree and returns it.
|
|
// Returns nil if the tree has no items.
|
|
func (tr *Map[K, V]) PopMin() (K, V, bool) {
|
|
if tr.root == nil {
|
|
return tr.empty.key, tr.empty.value, false
|
|
}
|
|
n := tr.isoLoad(&tr.root, true)
|
|
var item mapPair[K, V]
|
|
for {
|
|
n.count-- // optimistically update counts
|
|
if n.leaf() {
|
|
item = n.items[0]
|
|
if len(n.items) == tr.min {
|
|
break
|
|
}
|
|
copy(n.items[:], n.items[1:])
|
|
n.items[len(n.items)-1] = tr.empty
|
|
n.items = n.items[:len(n.items)-1]
|
|
tr.count--
|
|
if tr.count == 0 {
|
|
tr.root = nil
|
|
}
|
|
return item.key, item.value, true
|
|
}
|
|
n = tr.isoLoad(&(*n.children)[0], true)
|
|
}
|
|
// revert the counts
|
|
n = tr.root
|
|
for {
|
|
n.count++
|
|
if n.leaf() {
|
|
break
|
|
}
|
|
n = (*n.children)[0]
|
|
}
|
|
value, deleted := tr.Delete(item.key)
|
|
if deleted {
|
|
return item.key, value, true
|
|
}
|
|
return tr.empty.key, tr.empty.value, false
|
|
}
|
|
|
|
// PopMax removes the maximum item in tree and returns it.
|
|
// Returns nil if the tree has no items.
|
|
func (tr *Map[K, V]) PopMax() (K, V, bool) {
|
|
if tr.root == nil {
|
|
return tr.empty.key, tr.empty.value, false
|
|
}
|
|
n := tr.isoLoad(&tr.root, true)
|
|
var item mapPair[K, V]
|
|
for {
|
|
n.count-- // optimistically update counts
|
|
if n.leaf() {
|
|
item = n.items[len(n.items)-1]
|
|
if len(n.items) == tr.min {
|
|
break
|
|
}
|
|
n.items[len(n.items)-1] = tr.empty
|
|
n.items = n.items[:len(n.items)-1]
|
|
tr.count--
|
|
if tr.count == 0 {
|
|
tr.root = nil
|
|
}
|
|
return item.key, item.value, true
|
|
}
|
|
n = tr.isoLoad(&(*n.children)[len(*n.children)-1], true)
|
|
}
|
|
// revert the counts
|
|
n = tr.root
|
|
for {
|
|
n.count++
|
|
if n.leaf() {
|
|
break
|
|
}
|
|
n = (*n.children)[len(*n.children)-1]
|
|
}
|
|
value, deleted := tr.Delete(item.key)
|
|
if deleted {
|
|
return item.key, value, true
|
|
}
|
|
return tr.empty.key, tr.empty.value, false
|
|
}
|
|
|
|
// GetAt returns the value at index.
|
|
// Return nil if the tree is empty or the index is out of bounds.
|
|
func (tr *Map[K, V]) GetAt(index int) (K, V, bool) {
|
|
return tr.getAt(index, false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) GetAtMut(index int) (K, V, bool) {
|
|
return tr.getAt(index, true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) getAt(index int, mut bool) (K, V, bool) {
|
|
if tr.root == nil || index < 0 || index >= tr.count {
|
|
return tr.empty.key, tr.empty.value, false
|
|
}
|
|
n := tr.isoLoad(&tr.root, mut)
|
|
for {
|
|
if n.leaf() {
|
|
return n.items[index].key, n.items[index].value, true
|
|
}
|
|
i := 0
|
|
for ; i < len(n.items); i++ {
|
|
if index < (*n.children)[i].count {
|
|
break
|
|
} else if index == (*n.children)[i].count {
|
|
return n.items[i].key, n.items[i].value, true
|
|
}
|
|
index -= (*n.children)[i].count + 1
|
|
}
|
|
n = tr.isoLoad(&(*n.children)[i], mut)
|
|
}
|
|
}
|
|
|
|
// DeleteAt deletes the item at index.
|
|
// Return nil if the tree is empty or the index is out of bounds.
|
|
func (tr *Map[K, V]) DeleteAt(index int) (K, V, bool) {
|
|
if tr.root == nil || index < 0 || index >= tr.count {
|
|
return tr.empty.key, tr.empty.value, false
|
|
}
|
|
var pathbuf [8]uint8 // track the path
|
|
path := pathbuf[:0]
|
|
var item mapPair[K, V]
|
|
n := tr.isoLoad(&tr.root, true)
|
|
outer:
|
|
for {
|
|
n.count-- // optimistically update counts
|
|
if n.leaf() {
|
|
// the index is the item position
|
|
item = n.items[index]
|
|
if len(n.items) == tr.min {
|
|
path = append(path, uint8(index))
|
|
break outer
|
|
}
|
|
copy(n.items[index:], n.items[index+1:])
|
|
n.items[len(n.items)-1] = tr.empty
|
|
n.items = n.items[:len(n.items)-1]
|
|
tr.count--
|
|
if tr.count == 0 {
|
|
tr.root = nil
|
|
}
|
|
return item.key, item.value, true
|
|
}
|
|
i := 0
|
|
for ; i < len(n.items); i++ {
|
|
if index < (*n.children)[i].count {
|
|
break
|
|
} else if index == (*n.children)[i].count {
|
|
item = n.items[i]
|
|
path = append(path, uint8(i))
|
|
break outer
|
|
}
|
|
index -= (*n.children)[i].count + 1
|
|
}
|
|
path = append(path, uint8(i))
|
|
n = tr.isoLoad(&(*n.children)[i], true)
|
|
}
|
|
// revert the counts
|
|
n = tr.root
|
|
for i := 0; i < len(path); i++ {
|
|
n.count++
|
|
if !n.leaf() {
|
|
n = (*n.children)[uint8(path[i])]
|
|
}
|
|
}
|
|
value, deleted := tr.Delete(item.key)
|
|
if deleted {
|
|
return item.key, value, true
|
|
}
|
|
return tr.empty.key, tr.empty.value, false
|
|
}
|
|
|
|
// Height returns the height of the tree.
|
|
// Returns zero if tree has no items.
|
|
func (tr *Map[K, V]) Height() int {
|
|
var height int
|
|
if tr.root != nil {
|
|
n := tr.root
|
|
for {
|
|
height++
|
|
if n.leaf() {
|
|
break
|
|
}
|
|
n = (*n.children)[0]
|
|
}
|
|
}
|
|
return height
|
|
}
|
|
|
|
// MapIter represents an iterator for btree.Map
|
|
type MapIter[K ordered, V any] struct {
|
|
tr *Map[K, V]
|
|
mut bool
|
|
seeked bool
|
|
atstart bool
|
|
atend bool
|
|
stack []mapIterStackItem[K, V]
|
|
item mapPair[K, V]
|
|
}
|
|
|
|
type mapIterStackItem[K ordered, V any] struct {
|
|
n *mapNode[K, V]
|
|
i int
|
|
}
|
|
|
|
// Iter returns a read-only iterator.
|
|
func (tr *Map[K, V]) Iter() MapIter[K, V] {
|
|
return tr.iter(false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) IterMut() MapIter[K, V] {
|
|
return tr.iter(true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) iter(mut bool) MapIter[K, V] {
|
|
var iter MapIter[K, V]
|
|
iter.tr = tr
|
|
iter.mut = mut
|
|
return iter
|
|
}
|
|
|
|
// Seek to item greater-or-equal-to key.
|
|
// Returns false if there was no item found.
|
|
func (iter *MapIter[K, V]) Seek(key K) bool {
|
|
if iter.tr == nil {
|
|
return false
|
|
}
|
|
iter.seeked = true
|
|
iter.stack = iter.stack[:0]
|
|
if iter.tr.root == nil {
|
|
return false
|
|
}
|
|
n := iter.tr.isoLoad(&iter.tr.root, iter.mut)
|
|
for {
|
|
i, found := iter.tr.search(n, key)
|
|
iter.stack = append(iter.stack, mapIterStackItem[K, V]{n, i})
|
|
if found {
|
|
iter.item = n.items[i]
|
|
return true
|
|
}
|
|
if n.leaf() {
|
|
iter.stack[len(iter.stack)-1].i--
|
|
return iter.Next()
|
|
}
|
|
n = iter.tr.isoLoad(&(*n.children)[i], iter.mut)
|
|
}
|
|
}
|
|
|
|
// First moves iterator to first item in tree.
|
|
// Returns false if the tree is empty.
|
|
func (iter *MapIter[K, V]) First() bool {
|
|
if iter.tr == nil {
|
|
return false
|
|
}
|
|
iter.atend = false
|
|
iter.atstart = false
|
|
iter.seeked = true
|
|
iter.stack = iter.stack[:0]
|
|
if iter.tr.root == nil {
|
|
return false
|
|
}
|
|
n := iter.tr.isoLoad(&iter.tr.root, iter.mut)
|
|
for {
|
|
iter.stack = append(iter.stack, mapIterStackItem[K, V]{n, 0})
|
|
if n.leaf() {
|
|
break
|
|
}
|
|
n = iter.tr.isoLoad(&(*n.children)[0], iter.mut)
|
|
}
|
|
s := &iter.stack[len(iter.stack)-1]
|
|
iter.item = s.n.items[s.i]
|
|
return true
|
|
}
|
|
|
|
// Last moves iterator to last item in tree.
|
|
// Returns false if the tree is empty.
|
|
func (iter *MapIter[K, V]) Last() bool {
|
|
if iter.tr == nil {
|
|
return false
|
|
}
|
|
iter.seeked = true
|
|
iter.stack = iter.stack[:0]
|
|
if iter.tr.root == nil {
|
|
return false
|
|
}
|
|
n := iter.tr.isoLoad(&iter.tr.root, iter.mut)
|
|
for {
|
|
iter.stack = append(iter.stack, mapIterStackItem[K, V]{n, len(n.items)})
|
|
if n.leaf() {
|
|
iter.stack[len(iter.stack)-1].i--
|
|
break
|
|
}
|
|
n = iter.tr.isoLoad(&(*n.children)[len(n.items)], iter.mut)
|
|
}
|
|
s := &iter.stack[len(iter.stack)-1]
|
|
iter.item = s.n.items[s.i]
|
|
return true
|
|
}
|
|
|
|
// Next moves iterator to the next item in iterator.
|
|
// Returns false if the tree is empty or the iterator is at the end of
|
|
// the tree.
|
|
func (iter *MapIter[K, V]) Next() bool {
|
|
if iter.tr == nil {
|
|
return false
|
|
}
|
|
if !iter.seeked {
|
|
return iter.First()
|
|
}
|
|
if len(iter.stack) == 0 {
|
|
if iter.atstart {
|
|
return iter.First() && iter.Next()
|
|
}
|
|
return false
|
|
}
|
|
s := &iter.stack[len(iter.stack)-1]
|
|
s.i++
|
|
if s.n.leaf() {
|
|
if s.i == len(s.n.items) {
|
|
for {
|
|
iter.stack = iter.stack[:len(iter.stack)-1]
|
|
if len(iter.stack) == 0 {
|
|
iter.atend = true
|
|
return false
|
|
}
|
|
s = &iter.stack[len(iter.stack)-1]
|
|
if s.i < len(s.n.items) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
n := iter.tr.isoLoad(&(*s.n.children)[s.i], iter.mut)
|
|
for {
|
|
iter.stack = append(iter.stack, mapIterStackItem[K, V]{n, 0})
|
|
if n.leaf() {
|
|
break
|
|
}
|
|
n = iter.tr.isoLoad(&(*n.children)[0], iter.mut)
|
|
}
|
|
}
|
|
s = &iter.stack[len(iter.stack)-1]
|
|
iter.item = s.n.items[s.i]
|
|
return true
|
|
}
|
|
|
|
// Prev moves iterator to the previous item in iterator.
|
|
// Returns false if the tree is empty or the iterator is at the beginning of
|
|
// the tree.
|
|
func (iter *MapIter[K, V]) Prev() bool {
|
|
if iter.tr == nil {
|
|
return false
|
|
}
|
|
if !iter.seeked {
|
|
return false
|
|
}
|
|
if len(iter.stack) == 0 {
|
|
if iter.atend {
|
|
return iter.Last() && iter.Prev()
|
|
}
|
|
return false
|
|
}
|
|
s := &iter.stack[len(iter.stack)-1]
|
|
if s.n.leaf() {
|
|
s.i--
|
|
if s.i == -1 {
|
|
for {
|
|
iter.stack = iter.stack[:len(iter.stack)-1]
|
|
if len(iter.stack) == 0 {
|
|
iter.atstart = true
|
|
return false
|
|
}
|
|
s = &iter.stack[len(iter.stack)-1]
|
|
s.i--
|
|
if s.i > -1 {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
n := iter.tr.isoLoad(&(*s.n.children)[s.i], iter.mut)
|
|
for {
|
|
iter.stack = append(iter.stack,
|
|
mapIterStackItem[K, V]{n, len(n.items)})
|
|
if n.leaf() {
|
|
iter.stack[len(iter.stack)-1].i--
|
|
break
|
|
}
|
|
n = iter.tr.isoLoad(&(*n.children)[len(n.items)], iter.mut)
|
|
}
|
|
}
|
|
s = &iter.stack[len(iter.stack)-1]
|
|
iter.item = s.n.items[s.i]
|
|
return true
|
|
}
|
|
|
|
// Key returns the current iterator item key.
|
|
func (iter *MapIter[K, V]) Key() K {
|
|
return iter.item.key
|
|
}
|
|
|
|
// Value returns the current iterator item value.
|
|
func (iter *MapIter[K, V]) Value() V {
|
|
return iter.item.value
|
|
}
|
|
|
|
// Values returns all the values in order.
|
|
func (tr *Map[K, V]) Values() []V {
|
|
return tr.values(false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) ValuesMut() []V {
|
|
return tr.values(true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) values(mut bool) []V {
|
|
values := make([]V, 0, tr.Len())
|
|
if tr.root != nil {
|
|
values = tr.nodeValues(&tr.root, values, mut)
|
|
}
|
|
return values
|
|
}
|
|
|
|
func (tr *Map[K, V]) nodeValues(cn **mapNode[K, V], values []V, mut bool) []V {
|
|
n := tr.isoLoad(cn, mut)
|
|
if n.leaf() {
|
|
for i := 0; i < len(n.items); i++ {
|
|
values = append(values, n.items[i].value)
|
|
}
|
|
return values
|
|
}
|
|
for i := 0; i < len(n.items); i++ {
|
|
values = tr.nodeValues(&(*n.children)[i], values, mut)
|
|
values = append(values, n.items[i].value)
|
|
}
|
|
return tr.nodeValues(&(*n.children)[len(*n.children)-1], values, mut)
|
|
}
|
|
|
|
// Keys returns all the keys in order.
|
|
func (tr *Map[K, V]) Keys() []K {
|
|
keys := make([]K, 0, tr.Len())
|
|
if tr.root != nil {
|
|
keys = tr.root.keys(keys)
|
|
}
|
|
return keys
|
|
}
|
|
|
|
func (n *mapNode[K, V]) keys(keys []K) []K {
|
|
if n.leaf() {
|
|
for i := 0; i < len(n.items); i++ {
|
|
keys = append(keys, n.items[i].key)
|
|
}
|
|
return keys
|
|
}
|
|
for i := 0; i < len(n.items); i++ {
|
|
keys = (*n.children)[i].keys(keys)
|
|
keys = append(keys, n.items[i].key)
|
|
}
|
|
return (*n.children)[len(*n.children)-1].keys(keys)
|
|
}
|
|
|
|
// KeyValues returns all the keys and values in order.
|
|
func (tr *Map[K, V]) KeyValues() ([]K, []V) {
|
|
return tr.keyValues(false)
|
|
}
|
|
|
|
func (tr *Map[K, V]) KeyValuesMut() ([]K, []V) {
|
|
return tr.keyValues(true)
|
|
}
|
|
|
|
func (tr *Map[K, V]) keyValues(mut bool) ([]K, []V) {
|
|
keys := make([]K, 0, tr.Len())
|
|
values := make([]V, 0, tr.Len())
|
|
if tr.root != nil {
|
|
keys, values = tr.nodeKeyValues(&tr.root, keys, values, mut)
|
|
}
|
|
return keys, values
|
|
}
|
|
|
|
func (tr *Map[K, V]) nodeKeyValues(cn **mapNode[K, V], keys []K, values []V,
|
|
mut bool,
|
|
) ([]K, []V) {
|
|
n := tr.isoLoad(cn, mut)
|
|
if n.leaf() {
|
|
for i := 0; i < len(n.items); i++ {
|
|
keys = append(keys, n.items[i].key)
|
|
values = append(values, n.items[i].value)
|
|
}
|
|
return keys, values
|
|
}
|
|
for i := 0; i < len(n.items); i++ {
|
|
keys, values = tr.nodeKeyValues(&(*n.children)[i], keys, values, mut)
|
|
keys = append(keys, n.items[i].key)
|
|
values = append(values, n.items[i].value)
|
|
}
|
|
return tr.nodeKeyValues(&(*n.children)[len(*n.children)-1], keys, values,
|
|
mut)
|
|
}
|
|
|
|
// Clear will delete all items.
|
|
func (tr *Map[K, V]) Clear() {
|
|
tr.count = 0
|
|
tr.root = nil
|
|
}
|