From 3aa0eeddfb5fd7172af2f44d4b594c742e289b24 Mon Sep 17 00:00:00 2001 From: emirpasic Date: Sat, 7 Mar 2015 17:09:47 +0100 Subject: [PATCH] ArrayList addition (inc. test, example and documentation) --- README.md | 39 +++- examples/arraylist.go | 47 +++++ examples/arraystack.go | 2 +- examples/customcomparator.go | 2 +- examples/hashmap.go | 2 +- examples/hashset.go | 2 +- examples/linkedliststack.go | 2 +- examples/redblacktree.go | 2 +- examples/treemap.go | 2 +- examples/treeset.go | 2 +- lists/arraylist/arraylist.go | 182 ++++++++++++++++++ lists/arraylist/arraylist_test.go | 117 +++++++++++ lists/lists.go | 30 +++ maps/hashmap/hashmap_test.go | 12 ++ maps/treemap/treemap_test.go | 12 ++ sets/hashset/hashset.go | 2 +- sets/hashset/hashset_test.go | 12 ++ sets/sets.go | 6 +- sets/treeset/treeset_test.go | 12 ++ stacks/arraystack/arraystack.go | 23 ++- stacks/arraystack/arraystack_test.go | 3 - .../linkedliststack/linkedliststack_test.go | 3 - trees/redblacktree/redblacktree_test.go | 12 ++ 23 files changed, 496 insertions(+), 32 deletions(-) create mode 100644 examples/arraylist.go create mode 100644 lists/arraylist/arraylist.go create mode 100644 lists/arraylist/arraylist_test.go create mode 100644 lists/lists.go diff --git a/README.md b/README.md index 8d07a69..706066c 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Implementation of various data structures in Go. - [Sets](#sets) - [HashSet](#hashset) - [TreeSet](#treeset) +- [Lists](#lists) + - [ArrayList](#arraylist) - [Stacks](#stacks) - [LinkedListStack](#linkedliststack) - [ArrayStack](#arraystack) @@ -95,6 +97,41 @@ func main() { ``` +###Lists + +####ArrayList + +```go +package main + +import "github.com/emirpasic/gods/lists/arraylist" + +func main() { + list := arraylist.New() + + list.Add("a") // ["a"] + list.Add("b", "c") // ["a","b","c"] + + _, _ = list.Get(0) // "a",true + _, _ = list.Get(100) // nil,false + + _ = list.Contains("a", "b", "c") //true + _ = list.Contains("a", "b", "c", "d") //false + + list.Remove(2) // ["a","b"] + list.Remove(1) // ["a"] + list.Remove(0) // [] + list.Remove(0) // [] (ignored) + + _ = list.Empty() // true + _ = list.Size() // 0 + + list.Add("a") // ["a"] + list.Clear() // [] + +} +``` + ###Stacks The stack interface represents a last-in-first-out (LIFO) collection of objects. The usual push and pop operations are provided, as well as a method to peek at the top item on the stack, a method to check whether the stack is empty and the size (number of elements). @@ -457,6 +494,4 @@ For direct contributions, branch of from master and do _pull request_. ## License -Copyright (c) Emir Pasic , All rights reserved. - This library is distributed under the BSD-style license found in the [LICENSE](https://github.com/emirpasic/gods/blob/master/LICENSE) file. diff --git a/examples/arraylist.go b/examples/arraylist.go new file mode 100644 index 0000000..418a5ef --- /dev/null +++ b/examples/arraylist.go @@ -0,0 +1,47 @@ +/* +Copyright (c) 2015, Emir Pasic +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package examples + +import "github.com/emirpasic/gods/lists/arraylist" + +func ArrayListExample() { + list := arraylist.New() + list.Add("a") // ["a"] + list.Add("b", "c") // ["a","b","c"] + _, _ = list.Get(0) // "a",true + _, _ = list.Get(100) // nil,false + _ = list.Contains("a", "b", "c") // true + _ = list.Contains("a", "b", "c", "d") // false + list.Remove(2) // ["a","b"] + list.Remove(1) // ["a"] + list.Remove(0) // [] + list.Remove(0) // [] (ignored) + _ = list.Empty() // true + _ = list.Size() // 0 + list.Add("a") // ["a"] + list.Clear() // [] +} diff --git a/examples/arraystack.go b/examples/arraystack.go index 2e3fe1b..bad52af 100644 --- a/examples/arraystack.go +++ b/examples/arraystack.go @@ -28,7 +28,7 @@ package examples import "github.com/emirpasic/gods/stacks/arraystack" -func arraystackExample() { +func ArrayStackExample() { stack := arraystack.New() // empty stack.Push(1) // 1 stack.Push(2) // 1, 2 diff --git a/examples/customcomparator.go b/examples/customcomparator.go index de0d04a..b14e4af 100644 --- a/examples/customcomparator.go +++ b/examples/customcomparator.go @@ -53,7 +53,7 @@ func byID(a, b interface{}) int { } } -func exampleCustomComparator() { +func CustomComparatorExample() { set := treeset.NewWith(byID) set.Add(User{2, "Second"}) diff --git a/examples/hashmap.go b/examples/hashmap.go index 52a727a..f73882c 100644 --- a/examples/hashmap.go +++ b/examples/hashmap.go @@ -28,7 +28,7 @@ package examples import "github.com/emirpasic/gods/maps/hashmap" -func hashmapExample() { +func HashMapExample() { m := hashmap.New() // empty m.Put(1, "x") // 1->x m.Put(2, "b") // 2->b, 1->x (random order) diff --git a/examples/hashset.go b/examples/hashset.go index 19214ca..ed46674 100644 --- a/examples/hashset.go +++ b/examples/hashset.go @@ -28,7 +28,7 @@ package examples import "github.com/emirpasic/gods/sets/hashset" -func hashsetExample() { +func HashSetExample() { set := hashset.New() // empty (keys are of type int) set.Add(1) // 1 set.Add(2, 2, 3, 4, 5) // 3, 1, 2, 4, 5 (random order, duplicates ignored) diff --git a/examples/linkedliststack.go b/examples/linkedliststack.go index 61b21a3..ce77bcf 100644 --- a/examples/linkedliststack.go +++ b/examples/linkedliststack.go @@ -28,7 +28,7 @@ package examples import lls "github.com/emirpasic/gods/stacks/linkedliststack" -func linkedliststackExample() { +func LinkedListStackExample() { stack := lls.New() // empty stack.Push(1) // 1 stack.Push(2) // 1, 2 diff --git a/examples/redblacktree.go b/examples/redblacktree.go index 95add39..a5c54ec 100644 --- a/examples/redblacktree.go +++ b/examples/redblacktree.go @@ -31,7 +31,7 @@ import ( rbt "github.com/emirpasic/gods/trees/redblacktree" ) -func redblacktreeExample() { +func RedBlacTtreeExample() { tree := rbt.NewWithIntComparator() // empty(keys are of type int) tree.Put(1, "x") // 1->x diff --git a/examples/treemap.go b/examples/treemap.go index ab8a94d..45bea0b 100644 --- a/examples/treemap.go +++ b/examples/treemap.go @@ -28,7 +28,7 @@ package examples import "github.com/emirpasic/gods/maps/treemap" -func treemapExample() { +func TreeMapExample() { m := treemap.NewWithIntComparator() // empty (keys are of type int) m.Put(1, "x") // 1->x m.Put(2, "b") // 1->x, 2->b (in order) diff --git a/examples/treeset.go b/examples/treeset.go index cc2c546..62e717f 100644 --- a/examples/treeset.go +++ b/examples/treeset.go @@ -28,7 +28,7 @@ package examples import "github.com/emirpasic/gods/sets/treeset" -func treesetExample() { +func TreeSetExample() { set := treeset.NewWithIntComparator() // empty set.Add(1) // 1 set.Add(2, 2, 3, 4, 5) // 1, 2, 3, 4, 5 (in order, duplicates ignored) diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go new file mode 100644 index 0000000..3e3f13f --- /dev/null +++ b/lists/arraylist/arraylist.go @@ -0,0 +1,182 @@ +/* +Copyright (c) 2015, Emir Pasic +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// Implementation of list using a slice. +// Structure is not thread safe. +// References: http://en.wikipedia.org/wiki/List_%28abstract_data_type%29 + +package arraylist + +import ( + "fmt" + "github.com/emirpasic/gods/lists" + "strings" +) + +func assertInterfaceImplementation() { + var _ lists.Interface = (*List)(nil) +} + +type List struct { + elements []interface{} + size int +} + +const ( + GROWTH_FACTOR = float32(1.5) // growth by 50% + SHRINK_FACTOR = float32(0.5) // shrink when size is 50% of capacity (0 means never shrink) +) + +// Instantiates a new empty list +func New() *List { + return &List{} +} + +// Appends a value at the end of the list +func (list *List) Add(elements ...interface{}) { + list.growBy(len(elements)) + for _, element := range elements { + list.elements[list.size] = element + list.size += 1 + } +} + +// Returns the element at index. +// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false. +func (list *List) Get(index int) (interface{}, bool) { + + if !list.withinRange(index) { + return nil, false + } + + return list.elements[index], true +} + +// Removes one or more elements from the list with the supplied indices. +func (list *List) Remove(index int) { + + if !list.withinRange(index) { + return + } + + list.elements[index] = nil // cleanup reference + copy(list.elements[index:], list.elements[index+1:list.size]) // shift to the left by one (slow operation, need ways to optimize this) + list.size -= 1 + + list.shrink() +} + +// Check if elements (one or more) are present in the set. +// All elements have to be present in the set for the method to return true. +// Performance time complexity of n^2. +// Returns true if no arguments are passed at all, i.e. set is always super-set of empty set. +func (list *List) Contains(elements ...interface{}) bool { + + for _, searchElement := range elements { + found := false + for _, element := range list.elements { + if element == searchElement { + found = true + break + } + } + if !found { + return false + } + } + return true +} + +// Returns all elements in the list. +func (list *List) Values() []interface{} { + newElements := make([]interface{}, list.size, list.size) + copy(newElements, list.elements[:list.size]) + return newElements +} + +// Returns true if list does not contain any elements. +func (list *List) Empty() bool { + return list.size == 0 +} + +// Returns number of elements within the list. +func (list *List) Size() int { + return list.size +} + +// Removes all elements from the list. +func (list *List) Clear() { + list.size = 0 + list.elements = []interface{}{} +} + +func (list *List) String() string { + str := "ArrayList\n" + values := []string{} + for _, value := range list.elements { + values = append(values, fmt.Sprintf("%v", value)) + } + str += strings.Join(values, ", ") + return str +} + +/************* + * Internals * + *************/ + +// Check that the index is withing bounds of the list +func (list *List) withinRange(index int) bool { + return index >= 0 && index < list.size && list.size != 0 +} + +func (list *List) resize(cap int) { + newElements := make([]interface{}, cap, cap) + copy(newElements, list.elements) + list.elements = newElements +} + +// Expand the array if necessary, i.e. capacity will be reached if we add n elements +func (list *List) growBy(n int) { + // Grow when capacity is reached by a factor of 1.5 and add number of elements + currentCapacity := cap(list.elements) + if list.size+n >= currentCapacity { + newCapacity := int(GROWTH_FACTOR * float32(currentCapacity+n)) + list.resize(newCapacity) + } +} + +// Shrink the array if necessary, i.e. when size is SHRINK_FACTOR percent of current capacity +func (list *List) shrink() { + if SHRINK_FACTOR == 0.0 { + return + } + // Shrink when size is at SHRINK_FACTOR * capacity + currentCapacity := cap(list.elements) + if list.size <= int(float32(currentCapacity)*SHRINK_FACTOR) { + list.resize(list.size) + } + +} diff --git a/lists/arraylist/arraylist_test.go b/lists/arraylist/arraylist_test.go new file mode 100644 index 0000000..3f05f28 --- /dev/null +++ b/lists/arraylist/arraylist_test.go @@ -0,0 +1,117 @@ +/* +Copyright (c) 2015, Emir Pasic +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package arraylist + +import ( + "testing" +) + +func TestArrayList(t *testing.T) { + + list := New() + + list.Add("a", "b", "c", "d", "e", "f", "g") + list.Clear() + + if actualValue := list.Empty(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + if actualValue := list.Size(); actualValue != 0 { + t.Errorf("Got %v expected %v", actualValue, 0) + } + + list.Add("a") + list.Add("b", "c") + + if actualValue := list.Empty(); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + if actualValue := list.Size(); actualValue != 3 { + t.Errorf("Got %v expected %v", actualValue, 3) + } + + if actualValue, ok := list.Get(2); actualValue != "c" || !ok { + t.Errorf("Got %v expected %v", actualValue, "c") + } + + list.Remove(2) + + if actualValue, ok := list.Get(2); actualValue != nil || ok { + t.Errorf("Got %v expected %v", actualValue, nil) + } + + list.Remove(1) + list.Remove(0) + + if actualValue := list.Empty(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + if actualValue := list.Size(); actualValue != 0 { + t.Errorf("Got %v expected %v", actualValue, 0) + } + + list.Add("a", "b", "c") + + if actualValue := list.Contains("a", "b", "c"); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + if actualValue := list.Contains("a", "b", "c", "d"); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + list.Clear() + + if actualValue := list.Contains("a"); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + if actualValue, ok := list.Get(0); actualValue != nil || ok { + t.Errorf("Got %v expected %v", actualValue, false) + } + + if actualValue := list.Empty(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + +} + +func BenchmarkArrayList(b *testing.B) { + for i := 0; i < b.N; i++ { + list := New() + for n := 0; n < 1000; n++ { + list.Add(i) + } + for !list.Empty() { + list.Remove(0) + } + } + +} diff --git a/lists/lists.go b/lists/lists.go new file mode 100644 index 0000000..e76c1ef --- /dev/null +++ b/lists/lists.go @@ -0,0 +1,30 @@ +/* +Copyright (c) Emir Pasic, All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. See the file LICENSE included +with this distribution for more information. +*/ + +package lists + +type Interface interface { + Get(index int) (interface{}, bool) + Remove(index int) + Add(elements ...interface{}) + Contains(elements ...interface{}) bool + Empty() bool + Size() int + Clear() + Values() []interface{} +} diff --git a/maps/hashmap/hashmap_test.go b/maps/hashmap/hashmap_test.go index 73cebd1..46ffc0f 100644 --- a/maps/hashmap/hashmap_test.go +++ b/maps/hashmap/hashmap_test.go @@ -177,3 +177,15 @@ func sameElements(a []interface{}, b []interface{}) bool { } return true } + +func BenchmarkHashMap(b *testing.B) { + for i := 0; i < b.N; i++ { + m := New() + for n := 0; n < 1000; n++ { + m.Put(n, n) + } + for n := 0; n < 1000; n++ { + m.Remove(n) + } + } +} diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index b800cb1..314a052 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -159,3 +159,15 @@ func TestTreeMap(t *testing.T) { } } + +func BenchmarkTreeMap(b *testing.B) { + for i := 0; i < b.N; i++ { + m := NewWithIntComparator() + for n := 0; n < 1000; n++ { + m.Put(n, n) + } + for n := 0; n < 1000; n++ { + m.Remove(n) + } + } +} diff --git a/sets/hashset/hashset.go b/sets/hashset/hashset.go index e0506ad..dfd1069 100644 --- a/sets/hashset/hashset.go +++ b/sets/hashset/hashset.go @@ -65,7 +65,7 @@ func (set *Set) Remove(items ...interface{}) { } } -// Check wether items (one or more) are present in the set. +// Check if items (one or more) are present in the set. // All items have to be present in the set for the method to return true. // Returns true if no arguments are passed at all, i.e. set is always superset of empty set. func (set *Set) Contains(items ...interface{}) bool { diff --git a/sets/hashset/hashset_test.go b/sets/hashset/hashset_test.go index 7204872..d38006e 100644 --- a/sets/hashset/hashset_test.go +++ b/sets/hashset/hashset_test.go @@ -89,3 +89,15 @@ func TestHashSet(t *testing.T) { } } + +func BenchmarkHashSet(b *testing.B) { + for i := 0; i < b.N; i++ { + set := New() + for n := 0; n < 1000; n++ { + set.Add(i) + } + for n := 0; n < 1000; n++ { + set.Remove(n) + } + } +} diff --git a/sets/sets.go b/sets/sets.go index 07276e1..8cd4dd7 100644 --- a/sets/sets.go +++ b/sets/sets.go @@ -19,9 +19,9 @@ with this distribution for more information. package sets type Interface interface { - Add(items ...interface{}) - Remove(items ...interface{}) - Contains(items ...interface{}) bool + Add(elements ...interface{}) + Remove(elements ...interface{}) + Contains(elements ...interface{}) bool Empty() bool Size() int Clear() diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index 1d7b28c..4ad4265 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -84,3 +84,15 @@ func TestTreeSet(t *testing.T) { } } + +func BenchmarkTreeSet(b *testing.B) { + for i := 0; i < b.N; i++ { + set := NewWithIntComparator() + for n := 0; n < 1000; n++ { + set.Add(i) + } + for n := 0; n < 1000; n++ { + set.Remove(n) + } + } +} diff --git a/stacks/arraystack/arraystack.go b/stacks/arraystack/arraystack.go index 1522cdc..329d859 100644 --- a/stacks/arraystack/arraystack.go +++ b/stacks/arraystack/arraystack.go @@ -41,8 +41,8 @@ func assertInterfaceImplementation() { } type Stack struct { - items []interface{} - top int + elements []interface{} + top int } // Instantiates a new empty stack @@ -53,24 +53,23 @@ func New() *Stack { // Pushes a value onto the top of the stack func (stack *Stack) Push(value interface{}) { // Increase when capacity is reached by a factor of 1.5 and add one so it grows when size is zero - if stack.top+1 >= cap(stack.items) { - currentSize := len(stack.items) + if stack.top+1 >= cap(stack.elements) { + currentSize := len(stack.elements) sizeIncrease := int(1.5*float32(currentSize) + 1.0) newSize := currentSize + sizeIncrease newItems := make([]interface{}, newSize, newSize) - copy(newItems, stack.items) - stack.items = newItems + copy(newItems, stack.elements) + stack.elements = newItems } stack.top += 1 - stack.items[stack.top] = value + stack.elements[stack.top] = value } // Pops (removes) top element on stack and returns it, or nil if stack is empty. // Second return parameter is true, unless the stack was empty and there was nothing to pop. func (stack *Stack) Pop() (value interface{}, ok bool) { if stack.top >= 0 { - value, ok = stack.items[stack.top], true - // TODO shrink slice at some point + value, ok = stack.elements[stack.top], true stack.top -= 1 return } @@ -81,7 +80,7 @@ func (stack *Stack) Pop() (value interface{}, ok bool) { // Second return parameter is true, unless the stack was empty and there was nothing to peek. func (stack *Stack) Peek() (value interface{}, ok bool) { if stack.top >= 0 { - return stack.items[stack.top], true + return stack.elements[stack.top], true } return nil, false } @@ -99,13 +98,13 @@ func (stack *Stack) Size() int { // Removes all elements from the stack. func (stack *Stack) Clear() { stack.top = -1 - stack.items = []interface{}{} + stack.elements = []interface{}{} } func (stack *Stack) String() string { str := "ArrayStack\n" values := []string{} - for _, value := range stack.items { + for _, value := range stack.elements { values = append(values, fmt.Sprintf("%v", value)) } str += strings.Join(values, ", ") diff --git a/stacks/arraystack/arraystack_test.go b/stacks/arraystack/arraystack_test.go index 8738f51..7681c31 100644 --- a/stacks/arraystack/arraystack_test.go +++ b/stacks/arraystack/arraystack_test.go @@ -80,9 +80,6 @@ func TestArrayStack(t *testing.T) { } func BenchmarkArrayStack(b *testing.B) { - // Faster in comparison to the LinkedListStack - // BenchmarkArrayStack 5000 325010 ns/op 71648 B/op 1009 allocs/op - // BenchmarkLinkedListStack 5000 390812 ns/op 40016 B/op 2001 allocs/op for i := 0; i < b.N; i++ { stack := New() for n := 0; n < 1000; n++ { diff --git a/stacks/linkedliststack/linkedliststack_test.go b/stacks/linkedliststack/linkedliststack_test.go index 8dc47ef..79bec5a 100644 --- a/stacks/linkedliststack/linkedliststack_test.go +++ b/stacks/linkedliststack/linkedliststack_test.go @@ -80,9 +80,6 @@ func TestLinkedListStack(t *testing.T) { } func BenchmarkLinkedListStack(b *testing.B) { - // Slower in comparison to the ArrayStack - // BenchmarkArrayStack 5000 325010 ns/op 71648 B/op 1009 allocs/op - // BenchmarkLinkedListStack 5000 390812 ns/op 40016 B/op 2001 allocs/op for i := 0; i < b.N; i++ { stack := New() for n := 0; n < 1000; n++ { diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index b259517..b3ae6f3 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -159,3 +159,15 @@ func TestRedBlackTree(t *testing.T) { } } + +func BenchmarkRedBlackTree(b *testing.B) { + for i := 0; i < b.N; i++ { + tree := NewWithIntComparator() + for n := 0; n < 1000; n++ { + tree.Put(n, n) + } + for n := 0; n < 1000; n++ { + tree.Remove(n) + } + } +}