From 2df9ce1ab54c0517f269d2ed1d443fef4b7c2ab0 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 10 Jul 2016 22:03:59 +0200 Subject: [PATCH] - btree put fixes --- trees/btree/btree.go | 53 +++++-- trees/btree/btree_test.go | 326 ++++++++++++++++++++++++++------------ 2 files changed, 266 insertions(+), 113 deletions(-) diff --git a/trees/btree/btree.go b/trees/btree/btree.go index 578e807..18bcb53 100644 --- a/trees/btree/btree.go +++ b/trees/btree/btree.go @@ -26,7 +26,7 @@ type Tree struct { 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) + m int // order (maximum number of children) } // Node is a single element within the tree @@ -42,7 +42,7 @@ type Entry struct { Value interface{} } -// NewWith instantiates a B-tree with the Knuth order (maximum number of children) and a custom key comparator. +// NewWith instantiates a B-tree with the order (maximum number of children) and a custom key comparator. func NewWith(order int, comparator utils.Comparator) *Tree { if order < 2 { panic("Invalid order, should be at least 2") @@ -50,12 +50,12 @@ func NewWith(order int, comparator utils.Comparator) *Tree { 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. +// NewWithIntComparator instantiates a B-tree with the order (maximum number of children) and the IntComparator, i.e. keys are of type int. func NewWithIntComparator(order int) *Tree { return NewWith(order, utils.IntComparator) } -// NewWithStringComparator instantiates a B-tree with the Knuth order (maximum number of children) and the StringComparator, i.e. keys are of type string. +// NewWithStringComparator instantiates a B-tree with the order (maximum number of children) and the StringComparator, i.e. keys are of type string. func NewWithStringComparator(order int) *Tree { return NewWith(order, utils.StringComparator) } @@ -81,7 +81,20 @@ func (tree *Tree) Put(key interface{}, value interface{}) { // Second return parameter is true if key was found, otherwise false. // Key should adhere to the comparator's type assertion, otherwise method panics. func (tree *Tree) Get(key interface{}) (value interface{}, found bool) { - return nil, false + if tree.Empty() { + return nil, false + } + node := tree.Root + for { + index, found := tree.search(node, key) + if found { + return node.Entries[index].Value, true + } + if tree.isLeaf(node) { + return nil, false + } + node = node.Children[index] + } } // Remove remove the node from the tree by key. @@ -138,7 +151,6 @@ func (entry *Entry) String() string { func (tree *Tree) output(buffer *bytes.Buffer, node *Node, level int, isTail bool) { for e := 0; e < len(node.Entries)+1; e++ { if e < len(node.Children) { - buffer.WriteString(strings.Repeat(" ", level)) tree.output(buffer, node.Children[e], level+1, true) } if e < len(node.Entries) { @@ -183,12 +195,12 @@ func (tree *Tree) middle() int { return (tree.m - 1) / 2 // "-1" to favor right nodes to have more keys when splitting } -func (tree *Tree) search(node *Node, entry *Entry) (index int, found bool) { +func (tree *Tree) search(node *Node, key interface{}) (index int, found bool) { 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(key, node.Entries[mid].Key) switch { case compare > 0: low = mid + 1 @@ -209,11 +221,12 @@ 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) + insertPosition, found := tree.search(node, entry.Key) if found { node.Entries[insertPosition] = entry return false } + // Insert entry's key in the middle of the node node.Entries = append(node.Entries, nil) copy(node.Entries[insertPosition+1:], node.Entries[insertPosition:]) node.Entries[insertPosition] = entry @@ -222,7 +235,7 @@ 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) + insertPosition, found := tree.search(node, entry.Key) if found { node.Entries[insertPosition] = entry return false @@ -246,22 +259,30 @@ func (tree *Tree) split(node *Node) { func (tree *Tree) splitNonRoot(node *Node) { middle := tree.middle() parent := node.Parent + if node.Parent == nil { + panic("test") //TODO + } - left := &Node{Entries: node.Entries[:middle], Parent: parent} - right := &Node{Entries: node.Entries[middle+1:], Parent: parent} + left := &Node{Entries: append([]*Entry(nil), node.Entries[:middle]...), Parent: parent} + right := &Node{Entries: append([]*Entry(nil), node.Entries[middle+1:]...), Parent: parent} + // Move children from the node to be split into left and right nodes if !tree.isLeaf(node) { left.Children = node.Children[:middle+1] right.Children = node.Children[middle+1:] } - insertPosition, _ := tree.search(parent, node.Entries[middle]) + insertPosition, _ := tree.search(parent, node.Entries[middle].Key) + + // Insert middle key into parent parent.Entries = append(parent.Entries, nil) copy(parent.Entries[insertPosition+1:], parent.Entries[insertPosition:]) parent.Entries[insertPosition] = node.Entries[middle] + // Set child left of inserted key in parent to the created left node parent.Children[insertPosition] = left + // Set child right of inserted key in parent to the created right node parent.Children = append(parent.Children, nil) copy(parent.Children[insertPosition+2:], parent.Children[insertPosition+1:]) parent.Children[insertPosition+1] = right @@ -272,14 +293,16 @@ 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: append([]*Entry(nil), tree.Root.Entries[:middle]...)} + right := &Node{Entries: append([]*Entry(nil), tree.Root.Entries[middle+1:]...)} + // Move children from the node to be split into left and right nodes if !tree.isLeaf(tree.Root) { left.Children = tree.Root.Children[:middle+1] right.Children = tree.Root.Children[middle+1:] } + // Root is a node with one entry and two children (left and right) newRoot := &Node{ Entries: []*Entry{tree.Root.Entries[middle]}, Children: []*Node{left, right}, diff --git a/trees/btree/btree_test.go b/trees/btree/btree_test.go index 619c80f..0912bbf 100644 --- a/trees/btree/btree_test.go +++ b/trees/btree/btree_test.go @@ -5,194 +5,279 @@ package btree import ( - _ "fmt" + "fmt" "testing" ) -func TestBTree_search(t *testing.T) { - { - tree := NewWithIntComparator(3) - 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}) - if actualValue, expectedValue := index, test[1]; actualValue != expectedValue { - t.Errorf("Got %v expected %v", actualValue, expectedValue) - } - if actualValue, expectedValue := found, test[2]; actualValue != expectedValue { - t.Errorf("Got %v expected %v", actualValue, expectedValue) - } - } +func TestBTreeGet1(t *testing.T) { + tree := NewWithIntComparator(3) + tree.Put(1, "a") + tree.Put(2, "b") + tree.Put(3, "c") + tree.Put(4, "d") + tree.Put(5, "e") + tree.Put(6, "f") + tree.Put(7, "g") + + tests := [][]interface{}{ + {0, nil, false}, + {1, "a", true}, + {2, "b", true}, + {3, "c", true}, + {4, "d", true}, + {5, "e", true}, + {6, "f", true}, + {7, "g", true}, + {8, nil, false}, } - { - tree := NewWithIntComparator(3) - tree.Root = &Node{Entries: []*Entry{{2, 0}, {4, 1}, {6, 2}}, Children: []*Node{}} - tests := [][]interface{}{ - {0, 0, false}, - {1, 0, false}, - {2, 0, true}, - {3, 1, false}, - {4, 1, true}, - {5, 2, false}, - {6, 2, true}, - {7, 3, false}, - } - for _, test := range tests { - 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) - } - if actualValue, expectedValue := found, test[2]; actualValue != expectedValue { - t.Errorf("Got %v expected %v", actualValue, expectedValue) - } + + for _, test := range tests { + if value, found := tree.Get(test[0]); value != test[1] || found != test[2] { + t.Errorf("Got %v,%v expected %v,%v", value, found, test[1], test[2]) } } } -func TestBTree_insert1(t *testing.T) { +func TestBTreeGet2(t *testing.T) { + //tree := NewWithIntComparator(3) + //tree.Put(7, "g") + //tree.Put(9, "i") + //tree.Put(10, "j") + //tree.Put(6, "f") + //tree.Put(3, "c") + //tree.Put(4, "d") + //tree.Put(5, "e") + //tree.Put(8, "h") + //tree.Put(2, "b") + ////tree.Put(1, "a") + //fmt.Println(tree) + // + //tests := [][]interface{}{ + // {0, nil, false}, + // {1, "a", true}, + // {2, "b", true}, + // {3, "c", true}, + // {4, "d", true}, + // {5, "e", true}, + // {6, "f", true}, + // {7, "g", true}, + // {8, "h", true}, + // {9, "i", true}, + // {10, "j", true}, + // {11, nil, false}, + //} + // + //for _, test := range tests { + // if value, found := tree.Get(test[0]); value != test[1] || found != test[2] { + // t.Errorf("Got %v,%v expected %v,%v", value, found, test[1], test[2]) + // } + //} +} + +func TestBTreePut1(t *testing.T) { // https://upload.wikimedia.org/wikipedia/commons/3/33/B_tree_insertion_example.png tree := NewWithIntComparator(3) assertValidTree(t, tree, 0) tree.Put(1, 0) assertValidTree(t, tree, 1) - assertValidTreeNode(t, tree.Root, 1, 0, []int{1}) + assertValidTreeNode(t, tree.Root, 1, 0, []int{1}, false) 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}, false) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3}, true) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{3, 4}, true) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3}, true) + assertValidTreeNode(t, tree.Root.Children[2], 1, 0, []int{5}, true) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3}, true) + assertValidTreeNode(t, tree.Root.Children[2], 2, 0, []int{5, 6}, true) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{2}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{6}, true) + assertValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{3}, true) + assertValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{5}, true) + assertValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{7}, true) } -func TestBTree_insert2(t *testing.T) { +func TestBTreePut2(t *testing.T) { tree := NewWithIntComparator(4) assertValidTree(t, tree, 0) tree.Put(0, 0) assertValidTree(t, tree, 1) - assertValidTreeNode(t, tree.Root, 1, 0, []int{0}) + assertValidTreeNode(t, tree.Root, 1, 0, []int{0}, false) 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}, false) 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}, false) 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}, false) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0}, true) + assertValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{2, 3}, true) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0}, true) + assertValidTreeNode(t, tree.Root.Children[1], 3, 0, []int{2, 3, 4}, true) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{2}, true) + assertValidTreeNode(t, tree.Root.Children[2], 2, 0, []int{4, 5}, true) } -func TestBTree_insert3(t *testing.T) { +func TestBTreePut3(t *testing.T) { // http://www.geeksforgeeks.org/b-tree-set-1-insert-2/ tree := NewWithIntComparator(6) assertValidTree(t, tree, 0) tree.Put(10, 0) assertValidTree(t, tree, 1) - assertValidTreeNode(t, tree.Root, 1, 0, []int{10}) + assertValidTreeNode(t, tree.Root, 1, 0, []int{10}, false) 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}, false) 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}, false) 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}, false) 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}, false) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20}, true) + assertValidTreeNode(t, tree.Root.Children[1], 3, 0, []int{40, 50, 60}, true) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20}, true) + assertValidTreeNode(t, tree.Root.Children[1], 4, 0, []int{40, 50, 60, 70}, true) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20}, true) + assertValidTreeNode(t, tree.Root.Children[1], 5, 0, []int{40, 50, 60, 70, 80}, true) 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}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20}, true) + assertValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{40, 50}, true) + assertValidTreeNode(t, tree.Root.Children[2], 3, 0, []int{70, 80, 90}, true) +} + +func TestBTreePut4(t *testing.T) { + tree := NewWithIntComparator(3) + assertValidTree(t, tree, 0) + + tree.Put(6, nil) + assertValidTree(t, tree, 1) + assertValidTreeNode(t, tree.Root, 1, 0, []int{6}, false) + + tree.Put(5, nil) + assertValidTree(t, tree, 2) + assertValidTreeNode(t, tree.Root, 2, 0, []int{5, 6}, false) + + tree.Put(4, nil) + assertValidTree(t, tree, 3) + assertValidTreeNode(t, tree.Root, 1, 2, []int{5}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{4}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{6}, true) + + tree.Put(3, nil) + assertValidTreeNode(t, tree.Root, 1, 2, []int{5}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{3, 4}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{6}, true) + + tree.Put(2, nil) + assertValidTreeNode(t, tree.Root, 2, 3, []int{3, 5}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{2}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{4}, true) + assertValidTreeNode(t, tree.Root.Children[2], 1, 0, []int{6}, true) + + tree.Put(1, nil) + assertValidTreeNode(t, tree.Root, 2, 3, []int{3, 5}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{1, 2}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{4}, true) + assertValidTreeNode(t, tree.Root.Children[2], 1, 0, []int{6}, true) + + tree.Put(0, nil) + assertValidTreeNode(t, tree.Root, 1, 2, []int{3}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{5}, true) + assertValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{0}, true) + assertValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{2}, true) + assertValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{4}, true) + assertValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{6}, true) + + tree.Put(-1, nil) + assertValidTreeNode(t, tree.Root, 1, 2, []int{3}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{5}, true) + assertValidTreeNode(t, tree.Root.Children[0].Children[0], 2, 0, []int{-1, 0}, true) + assertValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{2}, true) + assertValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{4}, true) + assertValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{6}, true) + + fmt.Println(tree) + //tree.Put(-2, nil) + //tree.Put(-3, nil) + //tree.Put(-4, nil) + //tree.Put(-5, nil) + //tree.Put(-6, nil) + //fmt.Println(tree) } -func TestBTree_height(t *testing.T) { +func TestBTreeHeight(t *testing.T) { tree := NewWithIntComparator(3) if actualValue, expectedValue := tree.Height(), 0; actualValue != expectedValue { t.Errorf("Got %v expected %v", actualValue, expectedValue) @@ -234,13 +319,58 @@ func TestBTree_height(t *testing.T) { } } +func TestBTree_search(t *testing.T) { + { + tree := NewWithIntComparator(3) + tree.Root = &Node{Entries: []*Entry{}, Children: make([]*Node, 0)} + tests := [][]interface{}{ + {0, 0, false}, + } + for _, test := range tests { + index, found := tree.search(tree.Root, test[0]) + if actualValue, expectedValue := index, test[1]; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := found, test[2]; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + { + tree := NewWithIntComparator(3) + tree.Root = &Node{Entries: []*Entry{{2, 0}, {4, 1}, {6, 2}}, Children: []*Node{}} + tests := [][]interface{}{ + {0, 0, false}, + {1, 0, false}, + {2, 0, true}, + {3, 1, false}, + {4, 1, true}, + {5, 2, false}, + {6, 2, true}, + {7, 3, false}, + } + for _, test := range tests { + index, found := tree.search(tree.Root, test[0]) + if actualValue, expectedValue := index, test[1]; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := found, test[2]; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } +} + func assertValidTree(t *testing.T, tree *Tree, expectedSize int) { if actualValue, expectedValue := tree.size, expectedSize; actualValue != expectedValue { t.Errorf("Got %v expected %v for tree size", actualValue, expectedValue) } } -func assertValidTreeNode(t *testing.T, node *Node, expectedEntries int, expectedChildren int, keys []int) { +func assertValidTreeNode(t *testing.T, node *Node, expectedEntries int, expectedChildren int, keys []int, hasParent bool) { + if actualValue, expectedValue := node.Parent != nil, hasParent; actualValue != expectedValue { + t.Errorf("Got %v expected %v for hasParent", actualValue, expectedValue) + } if actualValue, expectedValue := len(node.Entries), expectedEntries; actualValue != expectedValue { t.Errorf("Got %v expected %v for entries size", actualValue, expectedValue) }