mirror of https://github.com/tidwall/tile38.git
replaced vendor btree with custom version
This commit is contained in:
parent
8ad3720a79
commit
bfa204067c
0
vendor/github.com/google/btree/LICENSE → vendor/github.com/tidwall/btree/LICENSE
generated
vendored
0
vendor/github.com/google/btree/LICENSE → vendor/github.com/tidwall/btree/LICENSE
generated
vendored
2
vendor/github.com/google/btree/README.md → vendor/github.com/tidwall/btree/README.md
generated
vendored
2
vendor/github.com/google/btree/README.md → vendor/github.com/tidwall/btree/README.md
generated
vendored
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master)
|
![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master)
|
||||||
|
|
||||||
This package provides an in-memory B-Tree implementation for Go, useful as a
|
This package provides an in-memory B-Tree implementation for Go, useful as
|
||||||
an ordered, mutable data structure.
|
an ordered, mutable data structure.
|
||||||
|
|
||||||
The API is based off of the wonderful
|
The API is based off of the wonderful
|
203
vendor/github.com/google/btree/btree.go → vendor/github.com/tidwall/btree/btree.go
generated
vendored
203
vendor/github.com/google/btree/btree.go → vendor/github.com/tidwall/btree/btree.go
generated
vendored
|
@ -44,7 +44,7 @@
|
||||||
// widely used ordered tree implementation in the Go ecosystem currently.
|
// widely used ordered tree implementation in the Go ecosystem currently.
|
||||||
// Its functions, therefore, exactly mirror those of
|
// Its functions, therefore, exactly mirror those of
|
||||||
// llrb.LLRB where possible. Unlike gollrb, though, we currently don't
|
// llrb.LLRB where possible. Unlike gollrb, though, we currently don't
|
||||||
// support storing multiple equivalent values or backwards iteration.
|
// support storing multiple equivalent values.
|
||||||
package btree
|
package btree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -61,7 +61,10 @@ type Item interface {
|
||||||
// This must provide a strict weak ordering.
|
// This must provide a strict weak ordering.
|
||||||
// If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only
|
// If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only
|
||||||
// hold one of either a or b in the tree).
|
// hold one of either a or b in the tree).
|
||||||
Less(than Item) bool
|
//
|
||||||
|
// There is a user-defined ctx argument that is equal to the ctx value which
|
||||||
|
// is set at time of the btree contruction.
|
||||||
|
Less(than Item, ctx int) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -106,18 +109,20 @@ type ItemIterator func(i Item) bool
|
||||||
//
|
//
|
||||||
// New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items
|
// New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items
|
||||||
// and 2-4 children).
|
// and 2-4 children).
|
||||||
func New(degree int) *BTree {
|
// The ctx param is user-defined.
|
||||||
return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize))
|
func New(degree, ctx int) *BTree {
|
||||||
|
return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize), ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWithFreeList creates a new B-Tree that uses the given node free list.
|
// NewWithFreeList creates a new B-Tree that uses the given node free list.
|
||||||
func NewWithFreeList(degree int, f *FreeList) *BTree {
|
func NewWithFreeList(degree int, f *FreeList, ctx int) *BTree {
|
||||||
if degree <= 1 {
|
if degree <= 1 {
|
||||||
panic("bad degree")
|
panic("bad degree")
|
||||||
}
|
}
|
||||||
return &BTree{
|
return &BTree{
|
||||||
degree: degree,
|
degree: degree,
|
||||||
freelist: f,
|
freelist: f,
|
||||||
|
ctx: ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,11 +161,11 @@ func (s *items) pop() (out Item) {
|
||||||
// find returns the index where the given item should be inserted into this
|
// find returns the index where the given item should be inserted into this
|
||||||
// list. 'found' is true if the item already exists in the list at the given
|
// list. 'found' is true if the item already exists in the list at the given
|
||||||
// index.
|
// index.
|
||||||
func (s items) find(item Item) (index int, found bool) {
|
func (s items) find(item Item, ctx int) (index int, found bool) {
|
||||||
i := sort.Search(len(s), func(i int) bool {
|
i := sort.Search(len(s), func(i int) bool {
|
||||||
return item.Less(s[i])
|
return item.Less(s[i], ctx)
|
||||||
})
|
})
|
||||||
if i > 0 && !s[i-1].Less(item) {
|
if i > 0 && !s[i-1].Less(item, ctx) {
|
||||||
return i - 1, true
|
return i - 1, true
|
||||||
}
|
}
|
||||||
return i, false
|
return i, false
|
||||||
|
@ -240,8 +245,8 @@ func (n *node) maybeSplitChild(i, maxItems int) bool {
|
||||||
// insert inserts an item into the subtree rooted at this node, making sure
|
// insert inserts an item into the subtree rooted at this node, making sure
|
||||||
// no nodes in the subtree exceed maxItems items. Should an equivalent item be
|
// no nodes in the subtree exceed maxItems items. Should an equivalent item be
|
||||||
// be found/replaced by insert, it will be returned.
|
// be found/replaced by insert, it will be returned.
|
||||||
func (n *node) insert(item Item, maxItems int) Item {
|
func (n *node) insert(item Item, maxItems int, ctx int) Item {
|
||||||
i, found := n.items.find(item)
|
i, found := n.items.find(item, ctx)
|
||||||
if found {
|
if found {
|
||||||
out := n.items[i]
|
out := n.items[i]
|
||||||
n.items[i] = item
|
n.items[i] = item
|
||||||
|
@ -254,9 +259,9 @@ func (n *node) insert(item Item, maxItems int) Item {
|
||||||
if n.maybeSplitChild(i, maxItems) {
|
if n.maybeSplitChild(i, maxItems) {
|
||||||
inTree := n.items[i]
|
inTree := n.items[i]
|
||||||
switch {
|
switch {
|
||||||
case item.Less(inTree):
|
case item.Less(inTree, ctx):
|
||||||
// no change, we want first split node
|
// no change, we want first split node
|
||||||
case inTree.Less(item):
|
case inTree.Less(item, ctx):
|
||||||
i++ // we want second split node
|
i++ // we want second split node
|
||||||
default:
|
default:
|
||||||
out := n.items[i]
|
out := n.items[i]
|
||||||
|
@ -264,16 +269,16 @@ func (n *node) insert(item Item, maxItems int) Item {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return n.children[i].insert(item, maxItems)
|
return n.children[i].insert(item, maxItems, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get finds the given key in the subtree and returns it.
|
// get finds the given key in the subtree and returns it.
|
||||||
func (n *node) get(key Item) Item {
|
func (n *node) get(key Item, ctx int) Item {
|
||||||
i, found := n.items.find(key)
|
i, found := n.items.find(key, ctx)
|
||||||
if found {
|
if found {
|
||||||
return n.items[i]
|
return n.items[i]
|
||||||
} else if len(n.children) > 0 {
|
} else if len(n.children) > 0 {
|
||||||
return n.children[i].get(key)
|
return n.children[i].get(key, ctx)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -316,7 +321,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// remove removes an item from the subtree rooted at this node.
|
// remove removes an item from the subtree rooted at this node.
|
||||||
func (n *node) remove(item Item, minItems int, typ toRemove) Item {
|
func (n *node) remove(item Item, minItems int, typ toRemove, ctx int) Item {
|
||||||
var i int
|
var i int
|
||||||
var found bool
|
var found bool
|
||||||
switch typ {
|
switch typ {
|
||||||
|
@ -331,7 +336,7 @@ func (n *node) remove(item Item, minItems int, typ toRemove) Item {
|
||||||
}
|
}
|
||||||
i = 0
|
i = 0
|
||||||
case removeItem:
|
case removeItem:
|
||||||
i, found = n.items.find(item)
|
i, found = n.items.find(item, ctx)
|
||||||
if len(n.children) == 0 {
|
if len(n.children) == 0 {
|
||||||
if found {
|
if found {
|
||||||
return n.items.removeAt(i)
|
return n.items.removeAt(i)
|
||||||
|
@ -344,7 +349,7 @@ func (n *node) remove(item Item, minItems int, typ toRemove) Item {
|
||||||
// If we get to here, we have children.
|
// If we get to here, we have children.
|
||||||
child := n.children[i]
|
child := n.children[i]
|
||||||
if len(child.items) <= minItems {
|
if len(child.items) <= minItems {
|
||||||
return n.growChildAndRemove(i, item, minItems, typ)
|
return n.growChildAndRemove(i, item, minItems, typ, ctx)
|
||||||
}
|
}
|
||||||
// Either we had enough items to begin with, or we've done some
|
// Either we had enough items to begin with, or we've done some
|
||||||
// merging/stealing, because we've got enough now and we're ready to return
|
// merging/stealing, because we've got enough now and we're ready to return
|
||||||
|
@ -356,12 +361,12 @@ func (n *node) remove(item Item, minItems int, typ toRemove) Item {
|
||||||
// We use our special-case 'remove' call with typ=maxItem to pull the
|
// We use our special-case 'remove' call with typ=maxItem to pull the
|
||||||
// predecessor of item i (the rightmost leaf of our immediate left child)
|
// predecessor of item i (the rightmost leaf of our immediate left child)
|
||||||
// and set it into where we pulled the item from.
|
// and set it into where we pulled the item from.
|
||||||
n.items[i] = child.remove(nil, minItems, removeMax)
|
n.items[i] = child.remove(nil, minItems, removeMax, ctx)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
// Final recursive call. Once we're here, we know that the item isn't in this
|
// Final recursive call. Once we're here, we know that the item isn't in this
|
||||||
// node and that the child is big enough to remove from.
|
// node and that the child is big enough to remove from.
|
||||||
return child.remove(item, minItems, typ)
|
return child.remove(item, minItems, typ, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// growChildAndRemove grows child 'i' to make sure it's possible to remove an
|
// growChildAndRemove grows child 'i' to make sure it's possible to remove an
|
||||||
|
@ -383,7 +388,7 @@ func (n *node) remove(item Item, minItems int, typ toRemove) Item {
|
||||||
// We then simply redo our remove call, and the second time (regardless of
|
// We then simply redo our remove call, and the second time (regardless of
|
||||||
// whether we're in case 1 or 2), we'll have enough items and can guarantee
|
// whether we're in case 1 or 2), we'll have enough items and can guarantee
|
||||||
// that we hit case A.
|
// that we hit case A.
|
||||||
func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove) Item {
|
func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove, ctx int) Item {
|
||||||
child := n.children[i]
|
child := n.children[i]
|
||||||
if i > 0 && len(n.children[i-1].items) > minItems {
|
if i > 0 && len(n.children[i-1].items) > minItems {
|
||||||
// Steal from left child
|
// Steal from left child
|
||||||
|
@ -416,37 +421,80 @@ func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove)
|
||||||
child.children = append(child.children, mergeChild.children...)
|
child.children = append(child.children, mergeChild.children...)
|
||||||
n.t.freeNode(mergeChild)
|
n.t.freeNode(mergeChild)
|
||||||
}
|
}
|
||||||
return n.remove(item, minItems, typ)
|
return n.remove(item, minItems, typ, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type direction int
|
||||||
|
|
||||||
|
const (
|
||||||
|
descend = direction(-1)
|
||||||
|
ascend = direction(+1)
|
||||||
|
)
|
||||||
|
|
||||||
// iterate provides a simple method for iterating over elements in the tree.
|
// iterate provides a simple method for iterating over elements in the tree.
|
||||||
// It could probably use some work to be extra-efficient (it calls from() a
|
|
||||||
// little more than it should), but it works pretty well for now.
|
|
||||||
//
|
//
|
||||||
// It requires that 'from' and 'to' both return true for values we should hit
|
// When ascending, the 'start' should be less than 'stop' and when descending,
|
||||||
// with the iterator. It should also be the case that 'from' returns true for
|
// the 'start' should be greater than 'stop'. Setting 'includeStart' to true
|
||||||
// values less than or equal to values 'to' returns true for, and 'to'
|
// will force the iterator to include the first item when it equals 'start',
|
||||||
// returns true for values greater than or equal to those that 'from'
|
// thus creating a "greaterOrEqual" or "lessThanEqual" rather than just a
|
||||||
// does.
|
// "greaterThan" or "lessThan" queries.
|
||||||
func (n *node) iterate(from, to func(Item) bool, iter ItemIterator) bool {
|
func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit bool, iter ItemIterator, ctx int) (bool, bool) {
|
||||||
for i, item := range n.items {
|
var ok bool
|
||||||
if !from(item) {
|
switch dir {
|
||||||
|
case ascend:
|
||||||
|
for i := 0; i < len(n.items); i++ {
|
||||||
|
if start != nil && n.items[i].Less(start, ctx) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(n.children) > 0 && !n.children[i].iterate(from, to, iter) {
|
if len(n.children) > 0 {
|
||||||
return false
|
if hit, ok = n.children[i].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
|
||||||
|
return hit, false
|
||||||
}
|
}
|
||||||
if !to(item) {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
if !iter(item) {
|
if !includeStart && !hit && start != nil && !start.Less(n.items[i], ctx) {
|
||||||
return false
|
hit = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hit = true
|
||||||
|
if stop != nil && !n.items[i].Less(stop, ctx) {
|
||||||
|
return hit, false
|
||||||
|
}
|
||||||
|
if !iter(n.items[i]) {
|
||||||
|
return hit, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(n.children) > 0 {
|
if len(n.children) > 0 {
|
||||||
return n.children[len(n.children)-1].iterate(from, to, iter)
|
if hit, ok = n.children[len(n.children)-1].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
|
||||||
|
return hit, false
|
||||||
}
|
}
|
||||||
return true
|
}
|
||||||
|
case descend:
|
||||||
|
for i := len(n.items) - 1; i >= 0; i-- {
|
||||||
|
if start != nil && !n.items[i].Less(start, ctx) {
|
||||||
|
if !includeStart || hit || start.Less(n.items[i], ctx) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(n.children) > 0 {
|
||||||
|
if hit, ok = n.children[i+1].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
|
||||||
|
return hit, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stop != nil && !stop.Less(n.items[i], ctx) {
|
||||||
|
return hit, false // continue
|
||||||
|
}
|
||||||
|
hit = true
|
||||||
|
if !iter(n.items[i]) {
|
||||||
|
return hit, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(n.children) > 0 {
|
||||||
|
if hit, ok = n.children[0].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
|
||||||
|
return hit, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hit, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for testing/debugging purposes.
|
// Used for testing/debugging purposes.
|
||||||
|
@ -469,6 +517,7 @@ type BTree struct {
|
||||||
length int
|
length int
|
||||||
root *node
|
root *node
|
||||||
freelist *FreeList
|
freelist *FreeList
|
||||||
|
ctx int
|
||||||
}
|
}
|
||||||
|
|
||||||
// maxItems returns the max number of items to allow per node.
|
// maxItems returns the max number of items to allow per node.
|
||||||
|
@ -522,7 +571,7 @@ func (t *BTree) ReplaceOrInsert(item Item) Item {
|
||||||
t.root.items = append(t.root.items, item2)
|
t.root.items = append(t.root.items, item2)
|
||||||
t.root.children = append(t.root.children, oldroot, second)
|
t.root.children = append(t.root.children, oldroot, second)
|
||||||
}
|
}
|
||||||
out := t.root.insert(item, t.maxItems())
|
out := t.root.insert(item, t.maxItems(), t.ctx)
|
||||||
if out == nil {
|
if out == nil {
|
||||||
t.length++
|
t.length++
|
||||||
}
|
}
|
||||||
|
@ -532,26 +581,26 @@ func (t *BTree) ReplaceOrInsert(item Item) Item {
|
||||||
// Delete removes an item equal to the passed in item from the tree, returning
|
// Delete removes an item equal to the passed in item from the tree, returning
|
||||||
// it. If no such item exists, returns nil.
|
// it. If no such item exists, returns nil.
|
||||||
func (t *BTree) Delete(item Item) Item {
|
func (t *BTree) Delete(item Item) Item {
|
||||||
return t.deleteItem(item, removeItem)
|
return t.deleteItem(item, removeItem, t.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteMin removes the smallest item in the tree and returns it.
|
// DeleteMin removes the smallest item in the tree and returns it.
|
||||||
// If no such item exists, returns nil.
|
// If no such item exists, returns nil.
|
||||||
func (t *BTree) DeleteMin() Item {
|
func (t *BTree) DeleteMin() Item {
|
||||||
return t.deleteItem(nil, removeMin)
|
return t.deleteItem(nil, removeMin, t.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteMax removes the largest item in the tree and returns it.
|
// DeleteMax removes the largest item in the tree and returns it.
|
||||||
// If no such item exists, returns nil.
|
// If no such item exists, returns nil.
|
||||||
func (t *BTree) DeleteMax() Item {
|
func (t *BTree) DeleteMax() Item {
|
||||||
return t.deleteItem(nil, removeMax)
|
return t.deleteItem(nil, removeMax, t.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *BTree) deleteItem(item Item, typ toRemove) Item {
|
func (t *BTree) deleteItem(item Item, typ toRemove, ctx int) Item {
|
||||||
if t.root == nil || len(t.root.items) == 0 {
|
if t.root == nil || len(t.root.items) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out := t.root.remove(item, t.minItems(), typ)
|
out := t.root.remove(item, t.minItems(), typ, ctx)
|
||||||
if len(t.root.items) == 0 && len(t.root.children) > 0 {
|
if len(t.root.items) == 0 && len(t.root.children) > 0 {
|
||||||
oldroot := t.root
|
oldroot := t.root
|
||||||
t.root = t.root.children[0]
|
t.root = t.root.children[0]
|
||||||
|
@ -569,10 +618,7 @@ func (t *BTree) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator
|
||||||
if t.root == nil {
|
if t.root == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.root.iterate(
|
t.root.iterate(ascend, greaterOrEqual, lessThan, true, false, iterator, t.ctx)
|
||||||
func(a Item) bool { return !a.Less(greaterOrEqual) },
|
|
||||||
func(a Item) bool { return a.Less(lessThan) },
|
|
||||||
iterator)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AscendLessThan calls the iterator for every value in the tree within the range
|
// AscendLessThan calls the iterator for every value in the tree within the range
|
||||||
|
@ -581,10 +627,7 @@ func (t *BTree) AscendLessThan(pivot Item, iterator ItemIterator) {
|
||||||
if t.root == nil {
|
if t.root == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.root.iterate(
|
t.root.iterate(ascend, nil, pivot, false, false, iterator, t.ctx)
|
||||||
func(a Item) bool { return true },
|
|
||||||
func(a Item) bool { return a.Less(pivot) },
|
|
||||||
iterator)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AscendGreaterOrEqual calls the iterator for every value in the tree within
|
// AscendGreaterOrEqual calls the iterator for every value in the tree within
|
||||||
|
@ -593,10 +636,7 @@ func (t *BTree) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) {
|
||||||
if t.root == nil {
|
if t.root == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.root.iterate(
|
t.root.iterate(ascend, pivot, nil, true, false, iterator, t.ctx)
|
||||||
func(a Item) bool { return !a.Less(pivot) },
|
|
||||||
func(a Item) bool { return true },
|
|
||||||
iterator)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ascend calls the iterator for every value in the tree within the range
|
// Ascend calls the iterator for every value in the tree within the range
|
||||||
|
@ -605,10 +645,43 @@ func (t *BTree) Ascend(iterator ItemIterator) {
|
||||||
if t.root == nil {
|
if t.root == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.root.iterate(
|
t.root.iterate(ascend, nil, nil, false, false, iterator, t.ctx)
|
||||||
func(a Item) bool { return true },
|
}
|
||||||
func(a Item) bool { return true },
|
|
||||||
iterator)
|
// DescendRange calls the iterator for every value in the tree within the range
|
||||||
|
// [lessOrEqual, greaterThan), until iterator returns false.
|
||||||
|
func (t *BTree) DescendRange(lessOrEqual, greaterThan Item, iterator ItemIterator) {
|
||||||
|
if t.root == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.root.iterate(descend, lessOrEqual, greaterThan, true, false, iterator, t.ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DescendLessOrEqual calls the iterator for every value in the tree within the range
|
||||||
|
// [pivot, first], until iterator returns false.
|
||||||
|
func (t *BTree) DescendLessOrEqual(pivot Item, iterator ItemIterator) {
|
||||||
|
if t.root == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.root.iterate(descend, pivot, nil, true, false, iterator, t.ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DescendGreaterThan calls the iterator for every value in the tree within
|
||||||
|
// the range [last, pivot), until iterator returns false.
|
||||||
|
func (t *BTree) DescendGreaterThan(pivot Item, iterator ItemIterator) {
|
||||||
|
if t.root == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.root.iterate(descend, nil, pivot, false, false, iterator, t.ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Descend calls the iterator for every value in the tree within the range
|
||||||
|
// [last, first], until iterator returns false.
|
||||||
|
func (t *BTree) Descend(iterator ItemIterator) {
|
||||||
|
if t.root == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.root.iterate(descend, nil, nil, false, false, iterator, t.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get looks for the key item in the tree, returning it. It returns nil if
|
// Get looks for the key item in the tree, returning it. It returns nil if
|
||||||
|
@ -617,7 +690,7 @@ func (t *BTree) Get(key Item) Item {
|
||||||
if t.root == nil {
|
if t.root == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return t.root.get(key)
|
return t.root.get(key, t.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Min returns the smallest item in the tree, or nil if the tree is empty.
|
// Min returns the smallest item in the tree, or nil if the tree is empty.
|
||||||
|
@ -644,6 +717,6 @@ func (t *BTree) Len() int {
|
||||||
type Int int
|
type Int int
|
||||||
|
|
||||||
// Less returns true if int(a) < int(b).
|
// Less returns true if int(a) < int(b).
|
||||||
func (a Int) Less(b Item) bool {
|
func (a Int) Less(b Item, ctx int) bool {
|
||||||
return a < b.(Int)
|
return a < b.(Int)
|
||||||
}
|
}
|
120
vendor/github.com/google/btree/btree_test.go → vendor/github.com/tidwall/btree/btree_test.go
generated
vendored
120
vendor/github.com/google/btree/btree_test.go → vendor/github.com/tidwall/btree/btree_test.go
generated
vendored
|
@ -54,10 +54,27 @@ func all(t *BTree) (out []Item) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rangerev returns a reversed ordered list of Int items in the range [0, n).
|
||||||
|
func rangrev(n int) (out []Item) {
|
||||||
|
for i := n - 1; i >= 0; i-- {
|
||||||
|
out = append(out, Int(i))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// allrev extracts all items from a tree in reverse order as a slice.
|
||||||
|
func allrev(t *BTree) (out []Item) {
|
||||||
|
t.Descend(func(a Item) bool {
|
||||||
|
out = append(out, a)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var btreeDegree = flag.Int("degree", 32, "B-Tree degree")
|
var btreeDegree = flag.Int("degree", 32, "B-Tree degree")
|
||||||
|
|
||||||
func TestBTree(t *testing.T) {
|
func TestBTree(t *testing.T) {
|
||||||
tr := New(*btreeDegree)
|
tr := New(*btreeDegree, 0)
|
||||||
const treeSize = 10000
|
const treeSize = 10000
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
if min := tr.Min(); min != nil {
|
if min := tr.Min(); min != nil {
|
||||||
|
@ -87,6 +104,13 @@ func TestBTree(t *testing.T) {
|
||||||
if !reflect.DeepEqual(got, want) {
|
if !reflect.DeepEqual(got, want) {
|
||||||
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
|
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gotrev := allrev(tr)
|
||||||
|
wantrev := rangrev(treeSize)
|
||||||
|
if !reflect.DeepEqual(gotrev, wantrev) {
|
||||||
|
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
for _, item := range perm(treeSize) {
|
for _, item := range perm(treeSize) {
|
||||||
if x := tr.Delete(item); x == nil {
|
if x := tr.Delete(item); x == nil {
|
||||||
t.Fatalf("didn't find %v", item)
|
t.Fatalf("didn't find %v", item)
|
||||||
|
@ -99,7 +123,7 @@ func TestBTree(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleBTree() {
|
func ExampleBTree() {
|
||||||
tr := New(*btreeDegree)
|
tr := New(*btreeDegree, 0)
|
||||||
for i := Int(0); i < 10; i++ {
|
for i := Int(0); i < 10; i++ {
|
||||||
tr.ReplaceOrInsert(i)
|
tr.ReplaceOrInsert(i)
|
||||||
}
|
}
|
||||||
|
@ -131,7 +155,7 @@ func ExampleBTree() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteMin(t *testing.T) {
|
func TestDeleteMin(t *testing.T) {
|
||||||
tr := New(3)
|
tr := New(3, 0)
|
||||||
for _, v := range perm(100) {
|
for _, v := range perm(100) {
|
||||||
tr.ReplaceOrInsert(v)
|
tr.ReplaceOrInsert(v)
|
||||||
}
|
}
|
||||||
|
@ -145,7 +169,7 @@ func TestDeleteMin(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteMax(t *testing.T) {
|
func TestDeleteMax(t *testing.T) {
|
||||||
tr := New(3)
|
tr := New(3, 0)
|
||||||
for _, v := range perm(100) {
|
for _, v := range perm(100) {
|
||||||
tr.ReplaceOrInsert(v)
|
tr.ReplaceOrInsert(v)
|
||||||
}
|
}
|
||||||
|
@ -163,7 +187,7 @@ func TestDeleteMax(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAscendRange(t *testing.T) {
|
func TestAscendRange(t *testing.T) {
|
||||||
tr := New(2)
|
tr := New(2, 0)
|
||||||
for _, v := range perm(100) {
|
for _, v := range perm(100) {
|
||||||
tr.ReplaceOrInsert(v)
|
tr.ReplaceOrInsert(v)
|
||||||
}
|
}
|
||||||
|
@ -188,8 +212,33 @@ func TestAscendRange(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDescendRange(t *testing.T) {
|
||||||
|
tr := New(2, 0)
|
||||||
|
for _, v := range perm(100) {
|
||||||
|
tr.ReplaceOrInsert(v)
|
||||||
|
}
|
||||||
|
var got []Item
|
||||||
|
tr.DescendRange(Int(60), Int(40), func(a Item) bool {
|
||||||
|
got = append(got, a)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if want := rangrev(100)[39:59]; !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want)
|
||||||
|
}
|
||||||
|
got = got[:0]
|
||||||
|
tr.DescendRange(Int(60), Int(40), func(a Item) bool {
|
||||||
|
if a.(Int) < 50 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
got = append(got, a)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
func TestAscendLessThan(t *testing.T) {
|
func TestAscendLessThan(t *testing.T) {
|
||||||
tr := New(*btreeDegree)
|
tr := New(*btreeDegree, 0)
|
||||||
for _, v := range perm(100) {
|
for _, v := range perm(100) {
|
||||||
tr.ReplaceOrInsert(v)
|
tr.ReplaceOrInsert(v)
|
||||||
}
|
}
|
||||||
|
@ -214,8 +263,33 @@ func TestAscendLessThan(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDescendLessOrEqual(t *testing.T) {
|
||||||
|
tr := New(*btreeDegree, 0)
|
||||||
|
for _, v := range perm(100) {
|
||||||
|
tr.ReplaceOrInsert(v)
|
||||||
|
}
|
||||||
|
var got []Item
|
||||||
|
tr.DescendLessOrEqual(Int(40), func(a Item) bool {
|
||||||
|
got = append(got, a)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if want := rangrev(100)[59:]; !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want)
|
||||||
|
}
|
||||||
|
got = got[:0]
|
||||||
|
tr.DescendLessOrEqual(Int(60), func(a Item) bool {
|
||||||
|
if a.(Int) < 50 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
got = append(got, a)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
func TestAscendGreaterOrEqual(t *testing.T) {
|
func TestAscendGreaterOrEqual(t *testing.T) {
|
||||||
tr := New(*btreeDegree)
|
tr := New(*btreeDegree, 0)
|
||||||
for _, v := range perm(100) {
|
for _, v := range perm(100) {
|
||||||
tr.ReplaceOrInsert(v)
|
tr.ReplaceOrInsert(v)
|
||||||
}
|
}
|
||||||
|
@ -240,6 +314,32 @@ func TestAscendGreaterOrEqual(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDescendGreaterThan(t *testing.T) {
|
||||||
|
tr := New(*btreeDegree, 0)
|
||||||
|
for _, v := range perm(100) {
|
||||||
|
tr.ReplaceOrInsert(v)
|
||||||
|
}
|
||||||
|
var got []Item
|
||||||
|
tr.DescendGreaterThan(Int(40), func(a Item) bool {
|
||||||
|
got = append(got, a)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if want := rangrev(100)[:59]; !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want)
|
||||||
|
}
|
||||||
|
got = got[:0]
|
||||||
|
tr.DescendGreaterThan(Int(40), func(a Item) bool {
|
||||||
|
if a.(Int) < 50 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
got = append(got, a)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if want := rangrev(100)[:50]; !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const benchmarkTreeSize = 10000
|
const benchmarkTreeSize = 10000
|
||||||
|
|
||||||
func BenchmarkInsert(b *testing.B) {
|
func BenchmarkInsert(b *testing.B) {
|
||||||
|
@ -248,7 +348,7 @@ func BenchmarkInsert(b *testing.B) {
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
i := 0
|
i := 0
|
||||||
for i < b.N {
|
for i < b.N {
|
||||||
tr := New(*btreeDegree)
|
tr := New(*btreeDegree, 0)
|
||||||
for _, item := range insertP {
|
for _, item := range insertP {
|
||||||
tr.ReplaceOrInsert(item)
|
tr.ReplaceOrInsert(item)
|
||||||
i++
|
i++
|
||||||
|
@ -267,7 +367,7 @@ func BenchmarkDelete(b *testing.B) {
|
||||||
i := 0
|
i := 0
|
||||||
for i < b.N {
|
for i < b.N {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
tr := New(*btreeDegree)
|
tr := New(*btreeDegree, 0)
|
||||||
for _, v := range insertP {
|
for _, v := range insertP {
|
||||||
tr.ReplaceOrInsert(v)
|
tr.ReplaceOrInsert(v)
|
||||||
}
|
}
|
||||||
|
@ -293,7 +393,7 @@ func BenchmarkGet(b *testing.B) {
|
||||||
i := 0
|
i := 0
|
||||||
for i < b.N {
|
for i < b.N {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
tr := New(*btreeDegree)
|
tr := New(*btreeDegree, 0)
|
||||||
for _, v := range insertP {
|
for _, v := range insertP {
|
||||||
tr.ReplaceOrInsert(v)
|
tr.ReplaceOrInsert(v)
|
||||||
}
|
}
|
Loading…
Reference in New Issue