diff --git a/trees/btree/btree.go b/trees/btree/btree.go index 87cdcb7..9738723 100644 --- a/trees/btree/btree.go +++ b/trees/btree/btree.go @@ -44,8 +44,8 @@ type Entry struct { // 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") + if order < 3 { + panic("Invalid order, should be at least 3") } return &Tree{m: order, Comparator: comparator} } @@ -134,6 +134,66 @@ func (tree *Tree) Height() int { return tree.Root.height() } +// Left returns the left-most (min) node or nil if tree is empty. +func (tree *Tree) Left() *Node { + if tree.Empty() { + return nil + } + node := tree.Root + for { + if tree.isLeaf(node) { + return node + } + node = node.Children[0] + } +} + +// LeftKey returns the left-most (min) key or nil if tree is empty. +func (tree *Tree) LeftKey() interface{} { + if left := tree.Left(); left != nil { + return left.Entries[0].Key + } + return nil +} + +// LeftValue returns the left-most value or nil if tree is empty. +func (tree *Tree) LeftValue() interface{} { + if left := tree.Left(); left != nil { + return left.Entries[0].Value + } + return nil +} + +// Right returns the right-most (max) node or nil if tree is empty. +func (tree *Tree) Right() *Node { + if tree.Empty() { + return nil + } + node := tree.Root + for { + if tree.isLeaf(node) { + return node + } + node = node.Children[len(node.Children)-1] + } +} + +// RightKey returns the right-most (max) key or nil if tree is empty. +func (tree *Tree) RightKey() interface{} { + if right := tree.Right(); right != nil { + return right.Entries[len(right.Entries)-1].Key + } + return nil +} + +// RightValue returns the right-most value or nil if tree is empty. +func (tree *Tree) RightValue() interface{} { + if right := tree.Right(); right != nil { + return right.Entries[len(right.Entries)-1].Value + } + return nil +} + // String returns a string representation of container (for debugging purposes) func (tree *Tree) String() string { var buffer bytes.Buffer diff --git a/trees/btree/btree_test.go b/trees/btree/btree_test.go index f41c425..dde69ef 100644 --- a/trees/btree/btree_test.go +++ b/trees/btree/btree_test.go @@ -350,6 +350,40 @@ func TestBTreeHeight(t *testing.T) { } } +func TestBTreeLeftAndRight(t *testing.T) { + tree := NewWithIntComparator(3) + + if actualValue := tree.Left(); actualValue != nil { + t.Errorf("Got %v expected %v", actualValue, nil) + } + if actualValue := tree.Right(); actualValue != nil { + t.Errorf("Got %v expected %v", actualValue, nil) + } + + tree.Put(1, "a") + tree.Put(5, "e") + tree.Put(6, "f") + tree.Put(7, "g") + tree.Put(3, "c") + tree.Put(4, "d") + tree.Put(1, "x") // overwrite + tree.Put(2, "b") + + if actualValue, expectedValue := tree.LeftKey(), 1; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := tree.LeftValue(), "x"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + if actualValue, expectedValue := tree.RightKey(), 7; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := tree.RightValue(), "g"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } +} + func TestBTree_search(t *testing.T) { { tree := NewWithIntComparator(3)