- btree expose its root, nodes and entries (for extension purposes)

pull/26/head
Emir Pasic 9 years ago
parent 19bf8e5c15
commit ab73314ad4

@ -21,22 +21,23 @@ func assertTreeImplementation() {
// Tree holds elements of the B-tree
type Tree struct {
root *Node // Root node
comparator utils.Comparator // Key comparator
Root *Node // Root node
Comparator utils.Comparator // Key comparator
size int // Total number of keys in the tree
m int // Knuth order (maximum number of children)
}
// Node is a single element within the tree
type Node struct {
parent *Node
entries []*Entry // Contained keys in node
children []*Node // Children nodes
Parent *Node
Entries []*Entry // Contained keys in node
Children []*Node // Children nodes
}
// Entry represents the key-value pair contained within nodes
type Entry struct {
key interface{}
value interface{}
Key interface{}
Value interface{}
}
// NewWith instantiates a B-tree with the Knuth order (maximum number of children) and a custom key comparator.
@ -44,7 +45,7 @@ func NewWith(order int, comparator utils.Comparator) *Tree {
if order < 2 {
panic("Invalid order, should be at least 2")
}
return &Tree{m: order, comparator: comparator}
return &Tree{m: order, Comparator: comparator}
}
// NewWithIntComparator instantiates a B-tree with the Knuth order (maximum number of children) and the IntComparator, i.e. keys are of type int.
@ -61,15 +62,15 @@ func NewWithStringComparator(order int) *Tree {
// If key already exists, then its value is updated with the new value.
// Key should adhere to the comparator's type assertion, otherwise method panics.
func (tree *Tree) Put(key interface{}, value interface{}) {
entry := &Entry{key: key, value: value}
entry := &Entry{Key: key, Value: value}
if tree.root == nil {
tree.root = &Node{entries: []*Entry{entry}, children: []*Node{}}
if tree.Root == nil {
tree.Root = &Node{Entries: []*Entry{entry}, Children: []*Node{}}
tree.size++
return
}
if tree.insert(tree.root, entry) {
if tree.insert(tree.Root, entry) {
tree.size++
}
}
@ -109,7 +110,7 @@ func (tree *Tree) Values() []interface{} {
// Clear removes all nodes from the tree.
func (tree *Tree) Clear() {
tree.root = nil
tree.Root = nil
tree.size = 0
}
@ -117,29 +118,29 @@ func (tree *Tree) Clear() {
func (tree *Tree) String() string {
str := "BTree\n"
if !tree.Empty() {
str += tree.root.String()
str += tree.Root.String()
}
return str
}
func (node *Node) String() string {
return fmt.Sprintf("%v", node.entries)
return fmt.Sprintf("%v", node.Entries)
}
func (entry *Entry) String() string {
return fmt.Sprintf("%v", entry.key)
return fmt.Sprintf("%v", entry.Key)
}
func (tree *Tree) isLeaf(node *Node) bool {
return len(node.children) == 0
return len(node.Children) == 0
}
func (tree *Tree) isFull(node *Node) bool {
return len(node.entries) == tree.maxEntries()
return len(node.Entries) == tree.maxEntries()
}
func (tree *Tree) shouldSplit(node *Node) bool {
return len(node.entries) > tree.maxEntries()
return len(node.Entries) > tree.maxEntries()
}
func (tree *Tree) maxChildren() int {
@ -155,11 +156,11 @@ func (tree *Tree) middle() int {
}
func (tree *Tree) search(node *Node, entry *Entry) (index int, found bool) {
low, high := 0, len(node.entries) - 1
low, high := 0, len(node.Entries)-1
var mid int
for low <= high {
mid = (high + low) / 2
compare := tree.comparator(entry.key, node.entries[mid].key)
compare := tree.Comparator(entry.Key, node.Entries[mid].Key)
switch {
case compare > 0:
low = mid + 1
@ -182,13 +183,13 @@ func (tree *Tree) insert(node *Node, entry *Entry) (inserted bool) {
func (tree *Tree) insertIntoLeaf(node *Node, entry *Entry) (inserted bool) {
insertPosition, found := tree.search(node, entry)
if found {
node.entries[insertPosition] = nil // GC
node.entries[insertPosition] = entry
node.Entries[insertPosition] = nil // GC
node.Entries[insertPosition] = entry
return false
}
node.entries = append(node.entries, nil)
copy(node.entries[insertPosition + 1:], node.entries[insertPosition:])
node.entries[insertPosition] = entry
node.Entries = append(node.Entries, nil)
copy(node.Entries[insertPosition+1:], node.Entries[insertPosition:])
node.Entries[insertPosition] = entry
tree.split(node)
return true
}
@ -196,11 +197,11 @@ func (tree *Tree) insertIntoLeaf(node *Node, entry *Entry) (inserted bool) {
func (tree *Tree) insertIntoInternal(node *Node, entry *Entry) (inserted bool) {
insertPosition, found := tree.search(node, entry)
if found {
node.entries[insertPosition] = nil // GC
node.entries[insertPosition] = entry
node.Entries[insertPosition] = nil // GC
node.Entries[insertPosition] = entry
return false
}
return tree.insert(node.children[insertPosition], entry)
return tree.insert(node.Children[insertPosition], entry)
}
func (tree *Tree) split(node *Node) {
@ -208,7 +209,7 @@ func (tree *Tree) split(node *Node) {
return
}
if node == tree.root {
if node == tree.Root {
tree.splitRoot()
return
}
@ -218,26 +219,26 @@ func (tree *Tree) split(node *Node) {
func (tree *Tree) splitNonRoot(node *Node) {
middle := tree.middle()
parent := node.parent
parent := node.Parent
left := &Node{entries: node.entries[:middle], parent: parent}
right := &Node{entries: node.entries[middle + 1:], parent: parent}
left := &Node{Entries: node.Entries[:middle], Parent: parent}
right := &Node{Entries: node.Entries[middle+1:], Parent: parent}
if !tree.isLeaf(node) {
left.children = node.children[:middle + 1]
right.children = node.children[middle + 1:]
left.Children = node.Children[:middle+1]
right.Children = node.Children[middle+1:]
}
insertPosition, _ := tree.search(parent, node.entries[middle])
parent.entries = append(parent.entries, nil)
copy(parent.entries[insertPosition + 1:], parent.entries[insertPosition:])
parent.entries[insertPosition] = node.entries[middle]
insertPosition, _ := tree.search(parent, node.Entries[middle])
parent.Entries = append(parent.Entries, nil)
copy(parent.Entries[insertPosition+1:], parent.Entries[insertPosition:])
parent.Entries[insertPosition] = node.Entries[middle]
parent.children[insertPosition] = left
parent.Children[insertPosition] = left
parent.children = append(parent.children, nil)
copy(parent.children[insertPosition + 2:], parent.children[insertPosition + 1:])
parent.children[insertPosition + 1] = right
parent.Children = append(parent.Children, nil)
copy(parent.Children[insertPosition+2:], parent.Children[insertPosition+1:])
parent.Children[insertPosition+1] = right
node = nil // GC
@ -247,20 +248,20 @@ func (tree *Tree) splitNonRoot(node *Node) {
func (tree *Tree) splitRoot() {
middle := tree.middle()
left := &Node{entries: tree.root.entries[:middle]}
right := &Node{entries: tree.root.entries[middle + 1:]}
left := &Node{Entries: tree.Root.Entries[:middle]}
right := &Node{Entries: tree.Root.Entries[middle+1:]}
if !tree.isLeaf(tree.root) {
left.children = tree.root.children[:middle + 1]
right.children = tree.root.children[middle + 1:]
if !tree.isLeaf(tree.Root) {
left.Children = tree.Root.Children[:middle+1]
right.Children = tree.Root.Children[middle+1:]
}
newRoot := &Node{
entries: []*Entry{tree.root.entries[middle]},
children: []*Node{left, right},
Entries: []*Entry{tree.Root.Entries[middle]},
Children: []*Node{left, right},
}
left.parent = newRoot
right.parent = newRoot
tree.root = newRoot
left.Parent = newRoot
right.Parent = newRoot
tree.Root = newRoot
}

@ -12,12 +12,12 @@ import (
func TestBTree_search(t *testing.T) {
{
tree := NewWithIntComparator(3)
tree.root = &Node{entries: []*Entry{}, children: make([]*Node, 0)}
tree.Root = &Node{Entries: []*Entry{}, Children: make([]*Node, 0)}
tests := [][]interface{}{
{0, 0, false},
}
for _, test := range tests {
index, found := tree.search(tree.root, &Entry{test[0], nil})
index, found := tree.search(tree.Root, &Entry{test[0], nil})
if actualValue, expectedValue := index, test[1]; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
@ -28,7 +28,7 @@ func TestBTree_search(t *testing.T) {
}
{
tree := NewWithIntComparator(3)
tree.root = &Node{entries: []*Entry{&Entry{2, 0}, &Entry{4, 1}, &Entry{6, 2}}, children: []*Node{}}
tree.Root = &Node{Entries: []*Entry{{2, 0}, {4, 1}, {6, 2}}, Children: []*Node{}}
tests := [][]interface{}{
{0, 0, false},
{1, 0, false},
@ -40,7 +40,7 @@ func TestBTree_search(t *testing.T) {
{7, 3, false},
}
for _, test := range tests {
index, found := tree.search(tree.root, &Entry{test[0], nil})
index, found := tree.search(tree.Root, &Entry{test[0], nil})
if actualValue, expectedValue := index, test[1]; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
@ -58,47 +58,47 @@ func TestBTree_insert1(t *testing.T) {
tree.Put(1, 0)
assertValidTree(t, tree, 1)
assertValidTreeNode(t, tree.root, 1, 0, []int{1})
assertValidTreeNode(t, tree.Root, 1, 0, []int{1})
tree.Put(2, 1)
assertValidTree(t, tree, 2)
assertValidTreeNode(t, tree.root, 2, 0, []int{1, 2})
assertValidTreeNode(t, tree.Root, 2, 0, []int{1, 2})
tree.Put(3, 2)
assertValidTree(t, tree, 3)
assertValidTreeNode(t, tree.root, 1, 2, []int{2})
assertValidTreeNode(t, tree.root.children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.root.children[1], 1, 0, []int{3})
assertValidTreeNode(t, tree.Root, 1, 2, []int{2})
assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3})
tree.Put(4, 2)
assertValidTree(t, tree, 4)
assertValidTreeNode(t, tree.root, 1, 2, []int{2})
assertValidTreeNode(t, tree.root.children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.root.children[1], 2, 0, []int{3, 4})
assertValidTreeNode(t, tree.Root, 1, 2, []int{2})
assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{3, 4})
tree.Put(5, 2)
assertValidTree(t, tree, 5)
assertValidTreeNode(t, tree.root, 2, 3, []int{2, 4})
assertValidTreeNode(t, tree.root.children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.root.children[1], 1, 0, []int{3})
assertValidTreeNode(t, tree.root.children[2], 1, 0, []int{5})
assertValidTreeNode(t, tree.Root, 2, 3, []int{2, 4})
assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3})
assertValidTreeNode(t, tree.Root.Children[2], 1, 0, []int{5})
tree.Put(6, 2)
assertValidTree(t, tree, 6)
assertValidTreeNode(t, tree.root, 2, 3, []int{2, 4})
assertValidTreeNode(t, tree.root.children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.root.children[1], 1, 0, []int{3})
assertValidTreeNode(t, tree.root.children[2], 2, 0, []int{5, 6})
assertValidTreeNode(t, tree.Root, 2, 3, []int{2, 4})
assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3})
assertValidTreeNode(t, tree.Root.Children[2], 2, 0, []int{5, 6})
tree.Put(7, 2)
assertValidTree(t, tree, 7)
assertValidTreeNode(t, tree.root, 1, 2, []int{4})
assertValidTreeNode(t, tree.root.children[0], 1, 2, []int{2})
assertValidTreeNode(t, tree.root.children[1], 1, 2, []int{6})
assertValidTreeNode(t, tree.root.children[0].children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.root.children[0].children[1], 1, 0, []int{3})
assertValidTreeNode(t, tree.root.children[1].children[0], 1, 0, []int{5})
assertValidTreeNode(t, tree.root.children[1].children[1], 1, 0, []int{7})
assertValidTreeNode(t, tree.Root, 1, 2, []int{4})
assertValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{2})
assertValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{6})
assertValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{1})
assertValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{3})
assertValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{5})
assertValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{7})
}
func TestBTree_insert2(t *testing.T) {
@ -107,38 +107,38 @@ func TestBTree_insert2(t *testing.T) {
tree.Put(0, 0)
assertValidTree(t, tree, 1)
assertValidTreeNode(t, tree.root, 1, 0, []int{0})
assertValidTreeNode(t, tree.Root, 1, 0, []int{0})
tree.Put(2, 2)
assertValidTree(t, tree, 2)
assertValidTreeNode(t, tree.root, 2, 0, []int{0, 2})
assertValidTreeNode(t, tree.Root, 2, 0, []int{0, 2})
tree.Put(1, 1)
assertValidTree(t, tree, 3)
assertValidTreeNode(t, tree.root, 3, 0, []int{0, 1, 2})
assertValidTreeNode(t, tree.Root, 3, 0, []int{0, 1, 2})
tree.Put(1, 1)
assertValidTree(t, tree, 3)
assertValidTreeNode(t, tree.root, 3, 0, []int{0, 1, 2})
assertValidTreeNode(t, tree.Root, 3, 0, []int{0, 1, 2})
tree.Put(3, 3)
assertValidTree(t, tree, 4)
assertValidTreeNode(t, tree.root, 1, 2, []int{1})
assertValidTreeNode(t, tree.root.children[0], 1, 0, []int{0})
assertValidTreeNode(t, tree.root.children[1], 2, 0, []int{2, 3})
assertValidTreeNode(t, tree.Root, 1, 2, []int{1})
assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0})
assertValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{2, 3})
tree.Put(4, 4)
assertValidTree(t, tree, 5)
assertValidTreeNode(t, tree.root, 1, 2, []int{1})
assertValidTreeNode(t, tree.root.children[0], 1, 0, []int{0})
assertValidTreeNode(t, tree.root.children[1], 3, 0, []int{2, 3, 4})
assertValidTreeNode(t, tree.Root, 1, 2, []int{1})
assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0})
assertValidTreeNode(t, tree.Root.Children[1], 3, 0, []int{2, 3, 4})
tree.Put(5, 5)
assertValidTree(t, tree, 6)
assertValidTreeNode(t, tree.root, 2, 3, []int{1, 3})
assertValidTreeNode(t, tree.root.children[0], 1, 0, []int{0})
assertValidTreeNode(t, tree.root.children[1], 1, 0, []int{2})
assertValidTreeNode(t, tree.root.children[2], 2, 0, []int{4, 5})
assertValidTreeNode(t, tree.Root, 2, 3, []int{1, 3})
assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0})
assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{2})
assertValidTreeNode(t, tree.Root.Children[2], 2, 0, []int{4, 5})
}
func TestBTree_insert3(t *testing.T) {
@ -148,48 +148,48 @@ func TestBTree_insert3(t *testing.T) {
tree.Put(10, 0)
assertValidTree(t, tree, 1)
assertValidTreeNode(t, tree.root, 1, 0, []int{10})
assertValidTreeNode(t, tree.Root, 1, 0, []int{10})
tree.Put(20, 1)
assertValidTree(t, tree, 2)
assertValidTreeNode(t, tree.root, 2, 0, []int{10, 20})
assertValidTreeNode(t, tree.Root, 2, 0, []int{10, 20})
tree.Put(30, 2)
assertValidTree(t, tree, 3)
assertValidTreeNode(t, tree.root, 3, 0, []int{10, 20, 30})
assertValidTreeNode(t, tree.Root, 3, 0, []int{10, 20, 30})
tree.Put(40, 3)
assertValidTree(t, tree, 4)
assertValidTreeNode(t, tree.root, 4, 0, []int{10, 20, 30, 40})
assertValidTreeNode(t, tree.Root, 4, 0, []int{10, 20, 30, 40})
tree.Put(50, 4)
assertValidTree(t, tree, 5)
assertValidTreeNode(t, tree.root, 5, 0, []int{10, 20, 30, 40, 50})
assertValidTreeNode(t, tree.Root, 5, 0, []int{10, 20, 30, 40, 50})
tree.Put(60, 5)
assertValidTree(t, tree, 6)
assertValidTreeNode(t, tree.root, 1, 2, []int{30})
assertValidTreeNode(t, tree.root.children[0], 2, 0, []int{10, 20})
assertValidTreeNode(t, tree.root.children[1], 3, 0, []int{40, 50, 60})
assertValidTreeNode(t, tree.Root, 1, 2, []int{30})
assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20})
assertValidTreeNode(t, tree.Root.Children[1], 3, 0, []int{40, 50, 60})
tree.Put(70, 6)
assertValidTree(t, tree, 7)
assertValidTreeNode(t, tree.root, 1, 2, []int{30})
assertValidTreeNode(t, tree.root.children[0], 2, 0, []int{10, 20})
assertValidTreeNode(t, tree.root.children[1], 4, 0, []int{40, 50, 60, 70})
assertValidTreeNode(t, tree.Root, 1, 2, []int{30})
assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20})
assertValidTreeNode(t, tree.Root.Children[1], 4, 0, []int{40, 50, 60, 70})
tree.Put(80, 7)
assertValidTree(t, tree, 8)
assertValidTreeNode(t, tree.root, 1, 2, []int{30})
assertValidTreeNode(t, tree.root.children[0], 2, 0, []int{10, 20})
assertValidTreeNode(t, tree.root.children[1], 5, 0, []int{40, 50, 60, 70, 80})
assertValidTreeNode(t, tree.Root, 1, 2, []int{30})
assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20})
assertValidTreeNode(t, tree.Root.Children[1], 5, 0, []int{40, 50, 60, 70, 80})
tree.Put(90, 8)
assertValidTree(t, tree, 9)
assertValidTreeNode(t, tree.root, 2, 3, []int{30, 60})
assertValidTreeNode(t, tree.root.children[0], 2, 0, []int{10, 20})
assertValidTreeNode(t, tree.root.children[1], 2, 0, []int{40, 50})
assertValidTreeNode(t, tree.root.children[2], 3, 0, []int{70, 80, 90})
assertValidTreeNode(t, tree.Root, 2, 3, []int{30, 60})
assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20})
assertValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{40, 50})
assertValidTreeNode(t, tree.Root.Children[2], 3, 0, []int{70, 80, 90})
}
func assertValidTree(t *testing.T, tree *Tree, expectedSize int) {
@ -199,14 +199,14 @@ func assertValidTree(t *testing.T, tree *Tree, expectedSize int) {
}
func assertValidTreeNode(t *testing.T, node *Node, expectedEntries int, expectedChildren int, keys []int) {
if actualValue, expectedValue := len(node.entries), expectedEntries; actualValue != expectedValue {
if actualValue, expectedValue := len(node.Entries), expectedEntries; actualValue != expectedValue {
t.Errorf("Got %v expected %v for entries size", actualValue, expectedValue)
}
if actualValue, expectedValue := len(node.children), expectedChildren; actualValue != expectedValue {
if actualValue, expectedValue := len(node.Children), expectedChildren; actualValue != expectedValue {
t.Errorf("Got %v expected %v for children size", actualValue, expectedValue)
}
for i, key := range keys {
if actualValue, expectedValue := node.entries[i].key, key; actualValue != expectedValue {
if actualValue, expectedValue := node.Entries[i].Key, key; actualValue != expectedValue {
t.Errorf("Got %v expected %v for key", actualValue, expectedValue)
}
}

@ -1,14 +0,0 @@
package main
import (
"github.com/emirpasic/gods/trees/btree"
"fmt"
)
func main() {
tree := btree.NewWithIntComparator(3)
tree.Put(1, 0)
tree.Put(2, 1)
tree.Put(3, 2)
fmt.Println()
}
Loading…
Cancel
Save