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)
|
||||
|
||||
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.
|
||||
|
||||
The API is based off of the wonderful
|
209
vendor/github.com/google/btree/btree.go → vendor/github.com/tidwall/btree/btree.go
generated
vendored
209
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.
|
||||
// Its functions, therefore, exactly mirror those of
|
||||
// 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
|
||||
|
||||
import (
|
||||
|
@ -61,7 +61,10 @@ type Item interface {
|
|||
// 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
|
||||
// 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 (
|
||||
|
@ -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
|
||||
// and 2-4 children).
|
||||
func New(degree int) *BTree {
|
||||
return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize))
|
||||
// The ctx param is user-defined.
|
||||
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.
|
||||
func NewWithFreeList(degree int, f *FreeList) *BTree {
|
||||
func NewWithFreeList(degree int, f *FreeList, ctx int) *BTree {
|
||||
if degree <= 1 {
|
||||
panic("bad degree")
|
||||
}
|
||||
return &BTree{
|
||||
degree: degree,
|
||||
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
|
||||
// list. 'found' is true if the item already exists in the list at the given
|
||||
// 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 {
|
||||
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, 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
|
||||
// no nodes in the subtree exceed maxItems items. Should an equivalent item be
|
||||
// be found/replaced by insert, it will be returned.
|
||||
func (n *node) insert(item Item, maxItems int) Item {
|
||||
i, found := n.items.find(item)
|
||||
func (n *node) insert(item Item, maxItems int, ctx int) Item {
|
||||
i, found := n.items.find(item, ctx)
|
||||
if found {
|
||||
out := n.items[i]
|
||||
n.items[i] = item
|
||||
|
@ -254,9 +259,9 @@ func (n *node) insert(item Item, maxItems int) Item {
|
|||
if n.maybeSplitChild(i, maxItems) {
|
||||
inTree := n.items[i]
|
||||
switch {
|
||||
case item.Less(inTree):
|
||||
case item.Less(inTree, ctx):
|
||||
// no change, we want first split node
|
||||
case inTree.Less(item):
|
||||
case inTree.Less(item, ctx):
|
||||
i++ // we want second split node
|
||||
default:
|
||||
out := n.items[i]
|
||||
|
@ -264,16 +269,16 @@ func (n *node) insert(item Item, maxItems int) Item {
|
|||
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.
|
||||
func (n *node) get(key Item) Item {
|
||||
i, found := n.items.find(key)
|
||||
func (n *node) get(key Item, ctx int) Item {
|
||||
i, found := n.items.find(key, ctx)
|
||||
if found {
|
||||
return n.items[i]
|
||||
} else if len(n.children) > 0 {
|
||||
return n.children[i].get(key)
|
||||
return n.children[i].get(key, ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -316,7 +321,7 @@ const (
|
|||
)
|
||||
|
||||
// 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 found bool
|
||||
switch typ {
|
||||
|
@ -331,7 +336,7 @@ func (n *node) remove(item Item, minItems int, typ toRemove) Item {
|
|||
}
|
||||
i = 0
|
||||
case removeItem:
|
||||
i, found = n.items.find(item)
|
||||
i, found = n.items.find(item, ctx)
|
||||
if len(n.children) == 0 {
|
||||
if found {
|
||||
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.
|
||||
child := n.children[i]
|
||||
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
|
||||
// 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
|
||||
// predecessor of item i (the rightmost leaf of our immediate left child)
|
||||
// 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
|
||||
}
|
||||
// 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.
|
||||
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
|
||||
|
@ -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
|
||||
// whether we're in case 1 or 2), we'll have enough items and can guarantee
|
||||
// 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]
|
||||
if i > 0 && len(n.children[i-1].items) > minItems {
|
||||
// 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...)
|
||||
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.
|
||||
// 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
|
||||
// with the iterator. It should also be the case that 'from' returns true for
|
||||
// values less than or equal to values 'to' returns true for, and 'to'
|
||||
// returns true for values greater than or equal to those that 'from'
|
||||
// does.
|
||||
func (n *node) iterate(from, to func(Item) bool, iter ItemIterator) bool {
|
||||
for i, item := range n.items {
|
||||
if !from(item) {
|
||||
continue
|
||||
// When ascending, the 'start' should be less than 'stop' and when descending,
|
||||
// the 'start' should be greater than 'stop'. Setting 'includeStart' to true
|
||||
// will force the iterator to include the first item when it equals 'start',
|
||||
// thus creating a "greaterOrEqual" or "lessThanEqual" rather than just a
|
||||
// "greaterThan" or "lessThan" queries.
|
||||
func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit bool, iter ItemIterator, ctx int) (bool, bool) {
|
||||
var ok bool
|
||||
switch dir {
|
||||
case ascend:
|
||||
for i := 0; i < len(n.items); i++ {
|
||||
if start != nil && n.items[i].Less(start, ctx) {
|
||||
continue
|
||||
}
|
||||
if len(n.children) > 0 {
|
||||
if hit, ok = n.children[i].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
|
||||
return hit, false
|
||||
}
|
||||
}
|
||||
if !includeStart && !hit && start != nil && !start.Less(n.items[i], ctx) {
|
||||
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 && !n.children[i].iterate(from, to, iter) {
|
||||
return false
|
||||
if len(n.children) > 0 {
|
||||
if hit, ok = n.children[len(n.children)-1].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
|
||||
return hit, false
|
||||
}
|
||||
}
|
||||
if !to(item) {
|
||||
return false
|
||||
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 !iter(item) {
|
||||
return false
|
||||
if len(n.children) > 0 {
|
||||
if hit, ok = n.children[0].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
|
||||
return hit, false
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(n.children) > 0 {
|
||||
return n.children[len(n.children)-1].iterate(from, to, iter)
|
||||
}
|
||||
return true
|
||||
return hit, true
|
||||
}
|
||||
|
||||
// Used for testing/debugging purposes.
|
||||
|
@ -469,6 +517,7 @@ type BTree struct {
|
|||
length int
|
||||
root *node
|
||||
freelist *FreeList
|
||||
ctx int
|
||||
}
|
||||
|
||||
// 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.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 {
|
||||
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
|
||||
// it. If no such item exists, returns nil.
|
||||
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.
|
||||
// If no such item exists, returns nil.
|
||||
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.
|
||||
// If no such item exists, returns nil.
|
||||
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 {
|
||||
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 {
|
||||
oldroot := t.root
|
||||
t.root = t.root.children[0]
|
||||
|
@ -569,10 +618,7 @@ func (t *BTree) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator
|
|||
if t.root == nil {
|
||||
return
|
||||
}
|
||||
t.root.iterate(
|
||||
func(a Item) bool { return !a.Less(greaterOrEqual) },
|
||||
func(a Item) bool { return a.Less(lessThan) },
|
||||
iterator)
|
||||
t.root.iterate(ascend, greaterOrEqual, lessThan, true, false, iterator, t.ctx)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return
|
||||
}
|
||||
t.root.iterate(
|
||||
func(a Item) bool { return true },
|
||||
func(a Item) bool { return a.Less(pivot) },
|
||||
iterator)
|
||||
t.root.iterate(ascend, nil, pivot, false, false, iterator, t.ctx)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return
|
||||
}
|
||||
t.root.iterate(
|
||||
func(a Item) bool { return !a.Less(pivot) },
|
||||
func(a Item) bool { return true },
|
||||
iterator)
|
||||
t.root.iterate(ascend, pivot, nil, true, false, iterator, t.ctx)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return
|
||||
}
|
||||
t.root.iterate(
|
||||
func(a Item) bool { return true },
|
||||
func(a Item) bool { return true },
|
||||
iterator)
|
||||
t.root.iterate(ascend, nil, nil, false, false, iterator, t.ctx)
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -617,7 +690,7 @@ func (t *BTree) Get(key Item) Item {
|
|||
if t.root == 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.
|
||||
|
@ -644,6 +717,6 @@ func (t *BTree) Len() int {
|
|||
type Int int
|
||||
|
||||
// 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)
|
||||
}
|
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
|
||||
}
|
||||
|
||||
// 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")
|
||||
|
||||
func TestBTree(t *testing.T) {
|
||||
tr := New(*btreeDegree)
|
||||
tr := New(*btreeDegree, 0)
|
||||
const treeSize = 10000
|
||||
for i := 0; i < 10; i++ {
|
||||
if min := tr.Min(); min != nil {
|
||||
|
@ -87,6 +104,13 @@ func TestBTree(t *testing.T) {
|
|||
if !reflect.DeepEqual(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) {
|
||||
if x := tr.Delete(item); x == nil {
|
||||
t.Fatalf("didn't find %v", item)
|
||||
|
@ -99,7 +123,7 @@ func TestBTree(t *testing.T) {
|
|||
}
|
||||
|
||||
func ExampleBTree() {
|
||||
tr := New(*btreeDegree)
|
||||
tr := New(*btreeDegree, 0)
|
||||
for i := Int(0); i < 10; i++ {
|
||||
tr.ReplaceOrInsert(i)
|
||||
}
|
||||
|
@ -131,7 +155,7 @@ func ExampleBTree() {
|
|||
}
|
||||
|
||||
func TestDeleteMin(t *testing.T) {
|
||||
tr := New(3)
|
||||
tr := New(3, 0)
|
||||
for _, v := range perm(100) {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
|
@ -145,7 +169,7 @@ func TestDeleteMin(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDeleteMax(t *testing.T) {
|
||||
tr := New(3)
|
||||
tr := New(3, 0)
|
||||
for _, v := range perm(100) {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
|
@ -163,7 +187,7 @@ func TestDeleteMax(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAscendRange(t *testing.T) {
|
||||
tr := New(2)
|
||||
tr := New(2, 0)
|
||||
for _, v := range perm(100) {
|
||||
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) {
|
||||
tr := New(*btreeDegree)
|
||||
tr := New(*btreeDegree, 0)
|
||||
for _, v := range perm(100) {
|
||||
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) {
|
||||
tr := New(*btreeDegree)
|
||||
tr := New(*btreeDegree, 0)
|
||||
for _, v := range perm(100) {
|
||||
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
|
||||
|
||||
func BenchmarkInsert(b *testing.B) {
|
||||
|
@ -248,7 +348,7 @@ func BenchmarkInsert(b *testing.B) {
|
|||
b.StartTimer()
|
||||
i := 0
|
||||
for i < b.N {
|
||||
tr := New(*btreeDegree)
|
||||
tr := New(*btreeDegree, 0)
|
||||
for _, item := range insertP {
|
||||
tr.ReplaceOrInsert(item)
|
||||
i++
|
||||
|
@ -267,7 +367,7 @@ func BenchmarkDelete(b *testing.B) {
|
|||
i := 0
|
||||
for i < b.N {
|
||||
b.StopTimer()
|
||||
tr := New(*btreeDegree)
|
||||
tr := New(*btreeDegree, 0)
|
||||
for _, v := range insertP {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
|
@ -293,7 +393,7 @@ func BenchmarkGet(b *testing.B) {
|
|||
i := 0
|
||||
for i < b.N {
|
||||
b.StopTimer()
|
||||
tr := New(*btreeDegree)
|
||||
tr := New(*btreeDegree, 0)
|
||||
for _, v := range insertP {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
Loading…
Reference in New Issue