diff --git a/treaps.go b/treaps.go index 1184deb..b83336f 100644 --- a/treaps.go +++ b/treaps.go @@ -1,5 +1,5 @@ // Package Treap exports a ordered set of arbitrary keys implemented through treaps. -// A treap is a kind of balanced binary search tree where their operations are O(log n). +// A treap is a kind of balanced binary Search tree where their operations are O(log n). package treaps import ( @@ -43,8 +43,8 @@ type Treap struct { less func(i1, i2 interface{}) bool } -// swap two treaps in O(1) -func (tree *Treap) swap(rhs *Treap) { +// Swap two treaps in O(1) +func (tree *Treap) Swap(rhs *Treap) { tree.seed, rhs.seed = rhs.seed, tree.seed tree.randGenerator, rhs.randGenerator = rhs.randGenerator, tree.randGenerator tree.rootPtr, rhs.rootPtr = rhs.rootPtr, tree.rootPtr @@ -74,7 +74,7 @@ func NewTreap(less func(i1, i2 interface{}) bool) *Treap { return New(time.Now().UTC().UnixNano(), less) } -// Helper function that perform an exact topological copy of tree rooted by p +// Helper function that perform an exact topological Copy of tree rooted by p func __copy(p *Node) *Node { if p == nullNodePtr { @@ -90,8 +90,8 @@ func __copy(p *Node) *Node { } } -// Get an exact copy of tree -func (tree *Treap) copy() *Treap { +// Get an exact Copy of tree +func (tree *Treap) Copy() *Treap { ret := New(tree.seed, tree.less) *ret.rootPtr = __copy(*tree.rootPtr) @@ -120,7 +120,7 @@ func __topologicalEqual(t1, t2 *Node, less func(i1, i2 interface{}) bool) bool { } // Return true if tree is topologically equivalent to rhs -func (tree *Treap) topologicalEqual(rhs *Treap) bool { +func (tree *Treap) TopologicalEqual(rhs *Treap) bool { return __topologicalEqual(*tree.rootPtr, *rhs.rootPtr, tree.less) } @@ -165,7 +165,7 @@ func __insertNode(root, p *Node, less func(i1, i2 interface{}) bool) *Node { // Insert item into the tree. Return nil if key is already contained; otherwise // returns the value of the just inserted item -func (tree *Treap) insert(item interface{}) interface{} { +func (tree *Treap) Insert(item interface{}) interface{} { p := &Node{ key: item, @@ -186,7 +186,7 @@ func (tree *Treap) insert(item interface{}) interface{} { // Search in tree key. If key is found, then the value contained in the set is returned. // Otherwise, the key was not found, nil value is returned -func (tree *Treap) search(key interface{}) interface{} { +func (tree *Treap) Search(key interface{}) interface{} { root := *tree.rootPtr for root != nullNodePtr { @@ -207,7 +207,7 @@ func (tree *Treap) search(key interface{}) interface{} { return root.key } -// Helper function for searching a node and eventually insert it into the tree if it is not found +// Helper function for searching a node and eventually Insert it into the tree if it is not found func __searchOrInsertNode(root **Node, p *Node, less func(i1, i2 interface{}) bool) *Node { if *root == nullNodePtr { @@ -242,7 +242,7 @@ func __searchOrInsertNode(root **Node, p *Node, less func(i1, i2 interface{}) bo // Search in tree item. If it is found, then the pair (false, item-value) is returned. // Otherwise, the item is inserted into the tree and the pair (true, item) is returned -func (tree *Treap) searchOrInsert(item interface{}) (bool, interface{}) { +func (tree *Treap) SearchOrInsert(item interface{}) (bool, interface{}) { p := &Node{ key: item, @@ -293,7 +293,7 @@ func __remove(rootPtr **Node, key interface{}, less func(i1, i2 interface{}) boo // Remove key from the tree. Return the removed value if the removal was successful. // Otherwise, the item was not found and the value nil is returned as signal of the failure -func (tree *Treap) remove(key interface{}) interface{} { +func (tree *Treap) Remove(key interface{}) interface{} { retVal := __remove(tree.rootPtr, key, tree.less) if retVal == nullNodePtr { @@ -304,7 +304,7 @@ func (tree *Treap) remove(key interface{}) interface{} { } // Return the smallest item contained in the tree -func (tree *Treap) min() interface{} { +func (tree *Treap) Min() interface{} { root := *tree.rootPtr if root == nullNodePtr { @@ -319,7 +319,7 @@ func (tree *Treap) min() interface{} { } // Return the greatest item contained in the tree -func (tree *Treap) max() interface{} { +func (tree *Treap) Max() interface{} { root := *tree.rootPtr if root == nullNodePtr { @@ -334,7 +334,7 @@ func (tree *Treap) max() interface{} { } // Return in O(1) the number of keys contained in the tree -func (tree *Treap) size() int { return (*tree.rootPtr).count } +func (tree *Treap) Size() int { return (*tree.rootPtr).count } // Helper function for splitting a tree according to key. The function returns two new trees. // tsRoot contains all the keys less than key and tgRoot contains the keys greater or equal to @@ -362,10 +362,10 @@ func __splitByKeyDup(root *Node, key interface{}, return tsRoot, tgRoot } -// split tree in two trees tsTree and tgTres. tsTree contains all the keys of tree in -// [tree.min(), key> and tgTree contains those ones in [key, tree.max]. After completion, +// SplitByKey tree in two trees tsTree and tgTres. tsTree contains all the keys of tree in +// [tree.Min(), key> and tgTree contains those ones in [key, tree.Max]. After completion, // tree becomes empty. -func (tree *Treap) split(key interface{}) (tsTree, tgTree *Treap) { +func (tree *Treap) SplitByKey(key interface{}) (tsTree, tgTree *Treap) { tsTree = New(tree.seed, tree.less) tgTree = New(tree.seed, tree.less) @@ -403,10 +403,12 @@ func __joinExclusive(tsRootPtr, tgRootPtr **Node) *Node { // join exclusive of tsTree with tgTree. Equivalent to append tgTree to tsTree. // tgTree must be greater than tsTree. Panic is thrown if this condition is not met -func (tsTree *Treap) joinExclusive(tgTree *Treap) { - if !tsTree.less(tsTree.max(), tgTree.min()) { +func (tsTree *Treap) JoinExclusive(tgTree *Treap) { + + if tsTree.Size() != 0 && tgTree.Size() != 0 && !tsTree.less(tsTree.Max(), tgTree.Min()) { panic("Trees are not range-disjoint") } + *tsTree.rootPtr = __joinExclusive(tsTree.rootPtr, tgTree.rootPtr) *tgTree.rootPtr = nullNodePtr } @@ -414,7 +416,7 @@ func (tsTree *Treap) joinExclusive(tgTree *Treap) { // Return the key located in the position pos respect to the order of the keys. // The item is retrieved in O(log n) expected time. // Panic if pos is greater or equal to the number of elements stored into the tree -func (tree *Treap) choose(pos int) interface{} { +func (tree *Treap) Choose(pos int) interface{} { root := *tree.rootPtr if pos >= root.count { @@ -461,14 +463,14 @@ func __rank(root *Node, key interface{}, less func(i1, i2 interface{}) bool) int // order of all keys stored in the tree. Otherwise, the method returns (false, Undetermined) // for indicating that the key is not in the tree. // The computation spends O(log n) expected time -func (tree *Treap) rank(key interface{}) (ok bool, pos int) { +func (tree *Treap) RankInOrder(key interface{}) (ok bool, pos int) { pos = __rank(*tree.rootPtr, key, tree.less) ok = pos != notFound return } -// Helper that split tree root by position i. i - 1 first minor keys are returned in l, +// Helper that SplitByKey tree root by position i. i - 1 first minor keys are returned in l, // while keys the following in r func __splitPos(root *Node, i int) (l, r *Node) { @@ -496,8 +498,8 @@ func __splitPos(root *Node, i int) (l, r *Node) { return } -// split tree in ts = [min, i) and tg = [i, max). After operation tree becomes empty -func (tree *Treap) splitPos(i int) (ts, tg *Treap) { +// SplitByKey tree in ts = [Min, i) and tg = [i, Max). After operation tree becomes empty +func (tree *Treap) SplitByPosition(i int) (ts, tg *Treap) { root := *tree.rootPtr if i > root.count { @@ -521,19 +523,19 @@ func (tree *Treap) splitPos(i int) (ts, tg *Treap) { } // Extract from tree all the keys in [beginPos, endPos). tree looses the extracted range -func (tree *Treap) extractRange(beginPos, endPos int) *Treap { +func (tree *Treap) ExtractRange(beginPos, endPos int) *Treap { if beginPos > endPos || endPos > (*tree.rootPtr).count-1 { panic(fmt.Sprintf("Invalid positions %d %d respect to number of keys %d", beginPos, endPos, (*tree.rootPtr).count)) } - treeAux, endTree := tree.splitPos(endPos) - beginTree, result := treeAux.splitPos(beginPos) + treeAux, endTree := tree.SplitByPosition(endPos) + beginTree, result := treeAux.SplitByPosition(beginPos) - beginTree.joinExclusive(endTree) + beginTree.JoinExclusive(endTree) - tree.swap(beginTree) + tree.Swap(beginTree) return result } @@ -600,29 +602,29 @@ func NewIterator(tree *Treap) *Iterator { return it } -func (it *Iterator) resetFirst() { +func (it *Iterator) ResetFirst() { emptyStack(it) initialize(it) } -func (it *Iterator) resetLast() { +func (it *Iterator) ResetLast() { emptyStack(it) advanceToMax(it, it.root) } -func (it *Iterator) hasCurr() bool { +func (it *Iterator) HasCurr() bool { return it.curr != nullNodePtr } -func (it *Iterator) getCurr() interface{} { - if !it.hasCurr() { +func (it *Iterator) GetCurr() interface{} { + if !it.HasCurr() { panic("Iterator has not current item") } return it.curr.key } -func (it *Iterator) next() { - if !it.hasCurr() { +func (it *Iterator) Next() { + if !it.HasCurr() { panic("Iterator has not current item") } it.curr = it.curr.rlink @@ -638,6 +640,8 @@ func (it *Iterator) next() { } } +// TODO Implement Prev method + // Simple BST checker; Not completely correct func checkBST(node *Node, less func(i1, i2 interface{}) bool) bool { diff --git a/treaps_test.go b/treaps_test.go index 420545a..4a5eb8b 100644 --- a/treaps_test.go +++ b/treaps_test.go @@ -23,7 +23,7 @@ func TestNewTreap(t *testing.T) { s := New(9, cmpInt) assert.NotNil(t, s) - assert.Equal(t, 0, s.size()) + assert.Equal(t, 0, s.Size()) } func TestTreap_insert(t *testing.T) { @@ -32,7 +32,7 @@ func TestTreap_insert(t *testing.T) { const N = 500 for i := 0; i < N; i++ { - ret := tree.insert(i) + ret := tree.Insert(i) assert.NotNil(t, ret) } } @@ -40,7 +40,7 @@ func TestTreap_insert(t *testing.T) { func insertNRandomItems(tree *Treap, n int) { for i := 0; i < n; i++ { val := rand.Intn(100 * n) - for tree.insert(val) == nil { + for tree.Insert(val) == nil { val = rand.Intn(100 * n) } } @@ -51,13 +51,13 @@ func TestRandomInsertions(t *testing.T) { const N = 500 for i := 0; i < N; i++ { val := rand.Intn(100 * N) - for tree.insert(val) == nil { + for tree.Insert(val) == nil { val = rand.Intn(100 * N) } - assert.Equal(t, val, tree.search(val)) + assert.Equal(t, val, tree.Search(val)) } - assert.Equal(t, N, int(tree.size())) + assert.Equal(t, N, int(tree.Size())) } func TestTreap_remove(t *testing.T) { @@ -66,15 +66,15 @@ func TestTreap_remove(t *testing.T) { insertNRandomItems(tree, N) - values := make([]int, 0, tree.size()) - for it := NewIterator(tree); it.hasCurr(); it.next() { - values = append(values, it.getCurr().(int)) + values := make([]int, 0, tree.Size()) + for it := NewIterator(tree); it.HasCurr(); it.Next() { + values = append(values, it.GetCurr().(int)) } for _, val := range values { - assert.Equal(t, val, tree.search(val)) - assert.Equal(t, val, tree.remove(val)) - assert.Equal(t, nil, tree.search(val)) + assert.Equal(t, val, tree.Search(val)) + assert.Equal(t, val, tree.Remove(val)) + assert.Equal(t, nil, tree.Search(val)) } } @@ -84,34 +84,34 @@ func TestTreap_split(t *testing.T) { const N = 100 insertNRandomItems(tree, N) - t1, t2 := tree.split(552) + t1, t2 := tree.SplitByKey(552) - assert.Equal(t, N, t1.size()+t2.size()) - assert.Equal(t, 0, tree.size()) + assert.Equal(t, N, t1.Size()+t2.Size()) + assert.Equal(t, 0, tree.Size()) - for it := NewIterator(t1); it.hasCurr(); it.next() { - fmt.Print(it.getCurr(), " ") + for it := NewIterator(t1); it.HasCurr(); it.Next() { + fmt.Print(it.GetCurr(), " ") } fmt.Println() - for it := NewIterator(t2); it.hasCurr(); it.next() { - fmt.Print(it.getCurr(), " ") + for it := NewIterator(t2); it.HasCurr(); it.Next() { + fmt.Print(it.GetCurr(), " ") } fmt.Println() - tree.joinExclusive(t1) + tree.JoinExclusive(t1) - for it := NewIterator(tree); it.hasCurr(); it.next() { - fmt.Print(it.getCurr(), " ") + for it := NewIterator(tree); it.HasCurr(); it.Next() { + fmt.Print(it.GetCurr(), " ") } fmt.Println() - tree.joinExclusive(t2) - assert.Equal(t, 0, t1.size()) - assert.Equal(t, 0, t2.size()) + tree.JoinExclusive(t2) + assert.Equal(t, 0, t1.Size()) + assert.Equal(t, 0, t2.Size()) - for it := NewIterator(tree); it.hasCurr(); it.next() { - fmt.Print(it.getCurr(), " ") + for it := NewIterator(tree); it.HasCurr(); it.Next() { + fmt.Print(it.GetCurr(), " ") } fmt.Println() } @@ -124,18 +124,18 @@ func TestTreap_searchOrInsert(t *testing.T) { for i := 0; i < N; i++ { val := rand.Intn(100 * N) - ok, res := tree.searchOrInsert(val) + ok, res := tree.SearchOrInsert(val) assert.Equal(t, val, res) if !ok { - failures.insert(val) + failures.Insert(val) } } - fmt.Println("tree.size() = ", tree.size()) - fmt.Println("failures.size() = ", failures.size()) + fmt.Println("tree.Size() = ", tree.Size()) + fmt.Println("failures.Size() = ", failures.Size()) - for it := NewIterator(failures); it.hasCurr(); it.next() { - assert.Equal(t, tree.search(it.getCurr()), it.getCurr()) + for it := NewIterator(failures); it.HasCurr(); it.Next() { + assert.Equal(t, tree.Search(it.GetCurr()), it.GetCurr()) } } @@ -145,9 +145,9 @@ func TestTreap_choose(t *testing.T) { const N = 1000 insertNRandomItems(tree, N) - for i, it := 0, NewIterator(tree); it.hasCurr(); it.next() { - item := tree.choose(i) - assert.Equal(t, item, it.getCurr()) + for i, it := 0, NewIterator(tree); it.HasCurr(); it.Next() { + item := tree.Choose(i) + assert.Equal(t, item, it.GetCurr()) i++ } } @@ -158,8 +158,8 @@ func TestTreap_rank(t *testing.T) { const N = 1000 insertNRandomItems(tree, N) - for i, it := 0, NewIterator(tree); it.hasCurr(); it.next() { - ok, pos := tree.rank(it.getCurr()) + for i, it := 0, NewIterator(tree); it.HasCurr(); it.Next() { + ok, pos := tree.RankInOrder(it.GetCurr()) assert.True(t, ok) assert.Equal(t, i, pos) i++ @@ -171,29 +171,29 @@ func TestTreap_splitPos(t *testing.T) { const N = 100 insertNRandomItems(tree, N) - min1, max1, min2, max2 := tree.min(), tree.choose(N/2-1), tree.choose(N/2), tree.max() + min1, max1, min2, max2 := tree.Min(), tree.Choose(N/2-1), tree.Choose(N/2), tree.Max() - t1, t2 := tree.splitPos(N / 2) + t1, t2 := tree.SplitByPosition(N / 2) - for it := NewIterator(t1); it.hasCurr(); it.next() { - fmt.Print(it.getCurr(), " ") + for it := NewIterator(t1); it.HasCurr(); it.Next() { + fmt.Print(it.GetCurr(), " ") } fmt.Println() - for it := NewIterator(t2); it.hasCurr(); it.next() { - fmt.Print(it.getCurr(), " ") + for it := NewIterator(t2); it.HasCurr(); it.Next() { + fmt.Print(it.GetCurr(), " ") } fmt.Println() - assert.Equal(t, 0, tree.size()) + assert.Equal(t, 0, tree.Size()) assert.NotNil(t, t1) assert.NotNil(t, t2) - assert.Equal(t, N/2, t1.size()) - assert.Equal(t, N/2, t2.size()) - assert.Equal(t, min1, t1.min()) - assert.Equal(t, max1, t1.max()) - assert.Equal(t, min2, t2.min()) - assert.Equal(t, max2, t2.max()) + assert.Equal(t, N/2, t1.Size()) + assert.Equal(t, N/2, t2.Size()) + assert.Equal(t, min1, t1.Min()) + assert.Equal(t, max1, t1.Max()) + assert.Equal(t, min2, t2.Min()) + assert.Equal(t, max2, t2.Max()) } func TestTreap_copy(t *testing.T) { @@ -205,38 +205,38 @@ func TestTreap_copy(t *testing.T) { assert.True(t, checkTreap(*t1.rootPtr)) assert.True(t, checkCounter(*t1.rootPtr)) - t2 := t1.copy() + t2 := t1.Copy() - for it := NewIterator(t1); it.hasCurr(); it.next() { - fmt.Print(it.getCurr(), " ") + for it := NewIterator(t1); it.HasCurr(); it.Next() { + fmt.Print(it.GetCurr(), " ") } fmt.Println() - for it := NewIterator(t2); it.hasCurr(); it.next() { - fmt.Print(it.getCurr(), " ") + for it := NewIterator(t2); it.HasCurr(); it.Next() { + fmt.Print(it.GetCurr(), " ") } fmt.Println() - assert.True(t, t1.topologicalEqual(t2)) + assert.True(t, t1.TopologicalEqual(t2)) } func TestTreap_removeRange(t *testing.T) { tree := New(2, cmpInt) const N = 100 for i := 0; i < N; i++ { - tree.insert(i) + tree.Insert(i) } - midRange := tree.extractRange(40, 60) + midRange := tree.ExtractRange(40, 60) - for key, it := 40, NewIterator(midRange); it.hasCurr(); it.next() { - assert.Equal(t, key, it.getCurr()) + for key, it := 40, NewIterator(midRange); it.HasCurr(); it.Next() { + assert.Equal(t, key, it.GetCurr()) key++ } fmt.Println() - for it := NewIterator(tree); it.hasCurr(); it.next() { - fmt.Print(it.getCurr(), " ") + for it := NewIterator(tree); it.HasCurr(); it.Next() { + fmt.Print(it.GetCurr(), " ") } fmt.Println()