From b86d413e66d49930536535e5d3e43ea45c84e0ee Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 26 Jun 2016 20:50:49 +0200 Subject: [PATCH 01/10] - iterator reset on all structures --- containers/iterator.go | 8 ++++++++ lists/arraylist/arraylist.go | 7 +++++++ lists/doublylinkedlist/doublylinkedlist.go | 8 ++++++++ lists/singlylinkedlist/singlylinkedlist.go | 8 ++++++++ maps/treemap/treemap.go | 7 +++++++ sets/treeset/treeset.go | 7 +++++++ stacks/arraystack/arraystack.go | 7 +++++++ stacks/linkedliststack/linkedliststack.go | 7 +++++++ trees/binaryheap/binaryheap.go | 7 +++++++ trees/redblacktree/redblacktree.go | 7 +++++++ 10 files changed, 73 insertions(+) diff --git a/containers/iterator.go b/containers/iterator.go index c1a7c54..8c08ba1 100644 --- a/containers/iterator.go +++ b/containers/iterator.go @@ -30,6 +30,7 @@ package containers type IteratorWithIndex interface { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). + // If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. Next() bool // Value returns the current element's value. @@ -38,12 +39,16 @@ type IteratorWithIndex interface { // Index returns the current element's index. // Does not modify the state of the iterator. Index() int + // Reset sets the iterator to the initial state. + // Call Next() to fetch the first element if any. + Reset() } // IteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs. type IteratorWithKey interface { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). + // If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. Next() bool // Value returns the current element's value. @@ -52,6 +57,9 @@ type IteratorWithKey interface { // Key returns the current element's key. // Does not modify the state of the iterator. Key() interface{} + // Reset sets the iterator to the initial state. + // Call Next() to fetch the first element if any. + Reset() } // ReverseIteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index. diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go index c08d928..909311b 100644 --- a/lists/arraylist/arraylist.go +++ b/lists/arraylist/arraylist.go @@ -193,6 +193,7 @@ func (list *List) Iterator() Iterator { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { if iterator.index < iterator.list.size { @@ -223,6 +224,12 @@ func (iterator *Iterator) Index() int { return iterator.index } +// Reset sets the iterator to the initial state. +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Reset() { + iterator.index = -1 +} + // Each calls the given function once for each element, passing that element's index and value. func (list *List) Each(f func(index int, value interface{})) { iterator := list.Iterator() diff --git a/lists/doublylinkedlist/doublylinkedlist.go b/lists/doublylinkedlist/doublylinkedlist.go index cb7bdfc..c5be4cf 100644 --- a/lists/doublylinkedlist/doublylinkedlist.go +++ b/lists/doublylinkedlist/doublylinkedlist.go @@ -314,6 +314,7 @@ func (list *List) Iterator() Iterator { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { if iterator.index < iterator.list.size { @@ -362,6 +363,13 @@ func (iterator *Iterator) Index() int { return iterator.index } +// Reset sets the iterator to the initial state. +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Reset() { + iterator.index = -1 + iterator.element = nil +} + // Each calls the given function once for each element, passing that element's index and value. func (list *List) Each(f func(index int, value interface{})) { iterator := list.Iterator() diff --git a/lists/singlylinkedlist/singlylinkedlist.go b/lists/singlylinkedlist/singlylinkedlist.go index f65f728..4a0eb1e 100644 --- a/lists/singlylinkedlist/singlylinkedlist.go +++ b/lists/singlylinkedlist/singlylinkedlist.go @@ -286,6 +286,7 @@ func (list *List) Iterator() Iterator { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { if iterator.index < iterator.list.size { @@ -315,6 +316,13 @@ func (iterator *Iterator) Index() int { return iterator.index } +// Reset sets the iterator to the initial state. +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Reset() { + iterator.index = -1 + iterator.element = nil +} + // Each calls the given function once for each element, passing that element's index and value. func (list *List) Each(f func(index int, value interface{})) { iterator := list.Iterator() diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index f1640bf..1b0f313 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -140,6 +140,7 @@ func (m *Map) Iterator() Iterator { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { return iterator.iterator.Next() @@ -164,6 +165,12 @@ func (iterator *Iterator) Key() interface{} { return iterator.iterator.Key() } +// Reset sets the iterator to the initial state. +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Reset() { + iterator.iterator.Reset() +} + // Each calls the given function once for each element, passing that element's key and value. func (m *Map) Each(f func(key interface{}, value interface{})) { iterator := m.Iterator() diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index 3a0de08..9a590ff 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -120,6 +120,7 @@ func (set *Set) Iterator() Iterator { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { if iterator.index < iterator.tree.Size() { @@ -150,6 +151,12 @@ func (iterator *Iterator) Index() int { return iterator.index } +// Reset sets the iterator to the initial state. +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Reset() { + iterator.iterator.Reset() +} + // Each calls the given function once for each element, passing that element's index and value. func (set *Set) Each(f func(index int, value interface{})) { iterator := set.Iterator() diff --git a/stacks/arraystack/arraystack.go b/stacks/arraystack/arraystack.go index ece76a9..07fa561 100644 --- a/stacks/arraystack/arraystack.go +++ b/stacks/arraystack/arraystack.go @@ -111,6 +111,7 @@ func (stack *Stack) Iterator() Iterator { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { if iterator.index < iterator.stack.Size() { @@ -142,6 +143,12 @@ func (iterator *Iterator) Index() int { return iterator.index } +// Reset sets the iterator to the initial state. +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Reset() { + iterator.index = -1 +} + // String returns a string representation of container func (stack *Stack) String() string { str := "ArrayStack\n" diff --git a/stacks/linkedliststack/linkedliststack.go b/stacks/linkedliststack/linkedliststack.go index 75f1948..f8cd31d 100644 --- a/stacks/linkedliststack/linkedliststack.go +++ b/stacks/linkedliststack/linkedliststack.go @@ -106,6 +106,7 @@ func (stack *Stack) Iterator() Iterator { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { if iterator.index < iterator.stack.Size() { @@ -127,6 +128,12 @@ func (iterator *Iterator) Index() int { return iterator.index } +// Reset sets the iterator to the initial state. +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Reset() { + iterator.index = -1 +} + // String returns a string representation of container func (stack *Stack) String() string { str := "LinkedListStack\n" diff --git a/trees/binaryheap/binaryheap.go b/trees/binaryheap/binaryheap.go index 0e5942f..a98f65e 100644 --- a/trees/binaryheap/binaryheap.go +++ b/trees/binaryheap/binaryheap.go @@ -127,6 +127,7 @@ func (heap *Heap) Iterator() Iterator { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { if iterator.index < iterator.heap.Size() { @@ -158,6 +159,12 @@ func (iterator *Iterator) Index() int { return iterator.index } +// Reset sets the iterator to the initial state. +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Reset() { + iterator.index = -1 +} + // String returns a string representation of container func (heap *Heap) String() string { str := "BinaryHeap\n" diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index cf68bab..01d22b4 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -291,6 +291,7 @@ func (tree *Tree) Iterator() Iterator { // Next moves the iterator to the next element and returns true if there was a next element in the container. // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { if iterator.node == nil { @@ -356,6 +357,12 @@ func (iterator *Iterator) Key() interface{} { return iterator.node.Key } +// Reset sets the iterator to the initial state. +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Reset() { + iterator.node = nil +} + // String returns a string representation of container func (tree *Tree) String() string { str := "RedBlackTree\n" From 3a938233a09e968142ce754ff357f99ce4d8f086 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 26 Jun 2016 21:44:23 +0200 Subject: [PATCH 02/10] - test iterator reset on all structures --- lists/arraylist/arraylist_test.go | 14 ++++++++++++++ lists/doublylinkedlist/doublylinkedlist_test.go | 14 ++++++++++++++ lists/singlylinkedlist/singlylinkedlist_test.go | 14 ++++++++++++++ maps/treemap/treemap_test.go | 16 ++++++++++++++++ sets/treeset/treeset.go | 1 + sets/treeset/treeset_test.go | 14 ++++++++++++++ stacks/arraystack/arraystack_test.go | 16 ++++++++++++++++ stacks/linkedliststack/linkedliststack_test.go | 16 ++++++++++++++++ trees/binaryheap/binaryheap_test.go | 16 ++++++++++++++++ trees/redblacktree/redblacktree_test.go | 16 ++++++++++++++++ 10 files changed, 137 insertions(+) diff --git a/lists/arraylist/arraylist_test.go b/lists/arraylist/arraylist_test.go index 9de67da..b4e131b 100644 --- a/lists/arraylist/arraylist_test.go +++ b/lists/arraylist/arraylist_test.go @@ -379,6 +379,20 @@ func TestListIteratorPrev(t *testing.T) { } } +func TestListIteratorReset(t *testing.T) { + list := New() + it := list.Iterator() + it.Reset() + list.Add("a", "b", "c") + for it.Next() { + } + it.Reset() + it.Next() + if index, value := it.Index(), it.Value(); index != 0 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") + } +} + func BenchmarkList(b *testing.B) { for i := 0; i < b.N; i++ { list := New() diff --git a/lists/doublylinkedlist/doublylinkedlist_test.go b/lists/doublylinkedlist/doublylinkedlist_test.go index 1ff73b6..e24f376 100644 --- a/lists/doublylinkedlist/doublylinkedlist_test.go +++ b/lists/doublylinkedlist/doublylinkedlist_test.go @@ -379,6 +379,20 @@ func TestListIteratorPrev(t *testing.T) { } } +func TestListIteratorReset(t *testing.T) { + list := New() + it := list.Iterator() + it.Reset() + list.Add("a", "b", "c") + for it.Next() { + } + it.Reset() + it.Next() + if index, value := it.Index(), it.Value(); index != 0 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") + } +} + func BenchmarkList(b *testing.B) { for i := 0; i < b.N; i++ { list := New() diff --git a/lists/singlylinkedlist/singlylinkedlist_test.go b/lists/singlylinkedlist/singlylinkedlist_test.go index 53c2ad8..6c0241d 100644 --- a/lists/singlylinkedlist/singlylinkedlist_test.go +++ b/lists/singlylinkedlist/singlylinkedlist_test.go @@ -338,6 +338,20 @@ func TestListIteratorNext(t *testing.T) { } } +func TestListIteratorReset(t *testing.T) { + list := New() + it := list.Iterator() + it.Reset() + list.Add("a", "b", "c") + for it.Next() { + } + it.Reset() + it.Next() + if index, value := it.Index(), it.Value(); index != 0 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") + } +} + func BenchmarkList(b *testing.B) { for i := 0; i < b.N; i++ { list := New() diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index ac4d778..228472c 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -406,6 +406,22 @@ func TestMapIteratorPrev(t *testing.T) { } } +func TestListIteratorReset(t *testing.T) { + m := NewWithIntComparator() + it := m.Iterator() + it.Reset() + m.Put(3, "c") + m.Put(1, "a") + m.Put(2, "b") + for it.Next() { + } + it.Reset() + it.Next() + if key, value := it.Key(), it.Value(); key != 1 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") + } +} + func BenchmarkMap(b *testing.B) { for i := 0; i < b.N; i++ { m := NewWithIntComparator() diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index 9a590ff..43a1717 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -154,6 +154,7 @@ func (iterator *Iterator) Index() int { // Reset sets the iterator to the initial state. // Call Next() to fetch the first element if any. func (iterator *Iterator) Reset() { + iterator.index = -1 iterator.iterator.Reset() } diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index ccdb16c..990cf3c 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -278,6 +278,20 @@ func TestSetIteratorPrev(t *testing.T) { } } +func TestListIteratorReset(t *testing.T) { + m := NewWithStringComparator() + it := m.Iterator() + it.Reset() + m.Add("a", "b", "c") + for it.Next() { + } + it.Reset() + it.Next() + if index, value := it.Index(), it.Value(); index != 0 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") + } +} + func BenchmarkSet(b *testing.B) { for i := 0; i < b.N; i++ { set := NewWithIntComparator() diff --git a/stacks/arraystack/arraystack_test.go b/stacks/arraystack/arraystack_test.go index fad4ac0..89faa43 100644 --- a/stacks/arraystack/arraystack_test.go +++ b/stacks/arraystack/arraystack_test.go @@ -176,6 +176,22 @@ func TestStackIteratorPrev(t *testing.T) { } } +func TestListIteratorReset(t *testing.T) { + stack := New() + it := stack.Iterator() + it.Reset() + stack.Push("a") + stack.Push("b") + stack.Push("c") + for it.Next() { + } + it.Reset() + it.Next() + if index, value := it.Index(), it.Value(); index != 0 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") + } +} + func BenchmarkStack(b *testing.B) { for i := 0; i < b.N; i++ { stack := New() diff --git a/stacks/linkedliststack/linkedliststack_test.go b/stacks/linkedliststack/linkedliststack_test.go index 4fb0002..f9f1df0 100644 --- a/stacks/linkedliststack/linkedliststack_test.go +++ b/stacks/linkedliststack/linkedliststack_test.go @@ -136,6 +136,22 @@ func TestStackIterator(t *testing.T) { } } +func TestListIteratorReset(t *testing.T) { + stack := New() + it := stack.Iterator() + it.Reset() + stack.Push("a") + stack.Push("b") + stack.Push("c") + for it.Next() { + } + it.Reset() + it.Next() + if index, value := it.Index(), it.Value(); index != 0 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") + } +} + func BenchmarkStack(b *testing.B) { for i := 0; i < b.N; i++ { stack := New() diff --git a/trees/binaryheap/binaryheap_test.go b/trees/binaryheap/binaryheap_test.go index d72375a..aed82c0 100644 --- a/trees/binaryheap/binaryheap_test.go +++ b/trees/binaryheap/binaryheap_test.go @@ -191,6 +191,22 @@ func TestBinaryHeapIteratorPrev(t *testing.T) { } } +func TestListIteratorReset(t *testing.T) { + tree := NewWithIntComparator() + it := tree.Iterator() + it.Reset() + tree.Push(2) + tree.Push(3) + tree.Push(1) + for it.Next() { + } + it.Reset() + it.Next() + if index, value := it.Index(), it.Value(); index != 0 || value != 1 { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, 1) + } +} + func BenchmarkBinaryHeap(b *testing.B) { for i := 0; i < b.N; i++ { heap := NewWithIntComparator() diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 3f5987a..3795859 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -496,6 +496,22 @@ func TestRedBlackTreeIterator4(t *testing.T) { } } +func TestListIteratorReset(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it := tree.Iterator() + it.Reset() + for it.Next() { + } + it.Reset() + it.Next() + if key, value := it.Key(), it.Value(); key != 1 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") + } +} + func BenchmarkRedBlackTree(b *testing.B) { for i := 0; i < b.N; i++ { tree := NewWithIntComparator() From f8b0747409454b9fb4a24c087758f94da04fb775 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 26 Jun 2016 22:27:08 +0200 Subject: [PATCH 03/10] - iterator last on all structures with reversible iterators --- containers/iterator.go | 20 ++++++++++++++++++-- lists/arraylist/arraylist.go | 8 ++++++++ lists/doublylinkedlist/doublylinkedlist.go | 9 +++++++++ maps/treemap/treemap.go | 7 +++++++ sets/treeset/treeset.go | 8 ++++++++ stacks/arraystack/arraystack.go | 8 ++++++++ trees/binaryheap/binaryheap.go | 8 ++++++++ trees/redblacktree/redblacktree.go | 8 ++++++++ 8 files changed, 74 insertions(+), 2 deletions(-) diff --git a/containers/iterator.go b/containers/iterator.go index 8c08ba1..9251550 100644 --- a/containers/iterator.go +++ b/containers/iterator.go @@ -64,12 +64,20 @@ type IteratorWithKey interface { // ReverseIteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index. // -// Essentially it is the same as IteratorWithIndex, but provides additional Prev() function to enable traversal in reverse. +// Essentially it is the same as IteratorWithIndex, but provides additional: +// +// Prev() function to enable traversal in reverse +// +// Last() function to move the iterator to the last element. type ReverseIteratorWithIndex interface { // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. Prev() bool + // Last moves the iterator to the last element and returns true if there was a last element in the container. + // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). + // Modifies the state of the iterator. + Last() bool IteratorWithIndex // Next() bool @@ -79,12 +87,20 @@ type ReverseIteratorWithIndex interface { // ReverseIteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs. // -// Essentially it is the same as IteratorWithKey, but provides additional Prev() function to enable traversal in reverse. +// Essentially it is the same as IteratorWithKey, but provides additional: +// +// Prev() function to enable traversal in reverse +// +// Last() function to move the iterator to the last element. type ReverseIteratorWithKey interface { // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. // If Prev() returns true, then previous element's index and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. Prev() bool + // Last moves the iterator to the last element and returns true if there was a last element in the container. + // If Last() returns true, then last element's index and value can be retrieved by Key() and Value(). + // Modifies the state of the iterator. + Last() bool IteratorWithKey // Next() bool diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go index 909311b..17d84d7 100644 --- a/lists/arraylist/arraylist.go +++ b/lists/arraylist/arraylist.go @@ -230,6 +230,14 @@ func (iterator *Iterator) Reset() { iterator.index = -1 } +// Last moves the iterator to the last element and returns true if there was a last element in the container. +// If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) Last() bool { + iterator.index = iterator.list.size + return iterator.Prev() +} + // Each calls the given function once for each element, passing that element's index and value. func (list *List) Each(f func(index int, value interface{})) { iterator := list.Iterator() diff --git a/lists/doublylinkedlist/doublylinkedlist.go b/lists/doublylinkedlist/doublylinkedlist.go index c5be4cf..7ef4047 100644 --- a/lists/doublylinkedlist/doublylinkedlist.go +++ b/lists/doublylinkedlist/doublylinkedlist.go @@ -370,6 +370,15 @@ func (iterator *Iterator) Reset() { iterator.element = nil } +// Last moves the iterator to the last element and returns true if there was a last element in the container. +// If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) Last() bool { + iterator.index = iterator.list.size + iterator.element = iterator.list.last + return iterator.Prev() +} + // Each calls the given function once for each element, passing that element's index and value. func (list *List) Each(f func(index int, value interface{})) { iterator := list.Iterator() diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index 1b0f313..424cae6 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -171,6 +171,13 @@ func (iterator *Iterator) Reset() { iterator.iterator.Reset() } +// Last moves the iterator to the last element and returns true if there was a last element in the container. +// If Last() returns true, then last element's index and value can be retrieved by Key() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) Last() bool { + return iterator.iterator.Last() +} + // Each calls the given function once for each element, passing that element's key and value. func (m *Map) Each(f func(key interface{}, value interface{})) { iterator := m.Iterator() diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index 43a1717..46feceb 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -158,6 +158,14 @@ func (iterator *Iterator) Reset() { iterator.iterator.Reset() } +// Last moves the iterator to the last element and returns true if there was a last element in the container. +// If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) Last() bool { + iterator.index = iterator.tree.Size() + return iterator.iterator.Last() +} + // Each calls the given function once for each element, passing that element's index and value. func (set *Set) Each(f func(index int, value interface{})) { iterator := set.Iterator() diff --git a/stacks/arraystack/arraystack.go b/stacks/arraystack/arraystack.go index 07fa561..ea65bdd 100644 --- a/stacks/arraystack/arraystack.go +++ b/stacks/arraystack/arraystack.go @@ -149,6 +149,14 @@ func (iterator *Iterator) Reset() { iterator.index = -1 } +// Last moves the iterator to the last element and returns true if there was a last element in the container. +// If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) Last() bool { + iterator.index = iterator.stack.Size() + return iterator.Prev() +} + // String returns a string representation of container func (stack *Stack) String() string { str := "ArrayStack\n" diff --git a/trees/binaryheap/binaryheap.go b/trees/binaryheap/binaryheap.go index a98f65e..e7819da 100644 --- a/trees/binaryheap/binaryheap.go +++ b/trees/binaryheap/binaryheap.go @@ -165,6 +165,14 @@ func (iterator *Iterator) Reset() { iterator.index = -1 } +// Last moves the iterator to the last element and returns true if there was a last element in the container. +// If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) Last() bool { + iterator.index = iterator.heap.Size() + return iterator.Prev() +} + // String returns a string representation of container func (heap *Heap) String() string { str := "BinaryHeap\n" diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index 01d22b4..b1ab99b 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -363,6 +363,14 @@ func (iterator *Iterator) Reset() { iterator.node = nil } +// Last moves the iterator to the last element and returns true if there was a last element in the container. +// If Last() returns true, then last element's index and value can be retrieved by Key() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) Last() bool { + iterator.node = iterator.tree.Right() + return iterator.node != nil +} + // String returns a string representation of container func (tree *Tree) String() string { str := "RedBlackTree\n" From 3d1014bf630eb3263a45b388aa1f5be34e29d501 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 26 Jun 2016 22:40:49 +0200 Subject: [PATCH 04/10] - test iterator last on all structures with reversible iterators --- lists/arraylist/arraylist_test.go | 15 +++++++++++++++ .../doublylinkedlist/doublylinkedlist_test.go | 15 +++++++++++++++ maps/treemap/treemap_test.go | 16 +++++++++++++++- sets/treeset/treeset_test.go | 14 +++++++++++++- stacks/arraystack/arraystack_test.go | 19 ++++++++++++++++++- .../linkedliststack/linkedliststack_test.go | 2 +- trees/binaryheap/binaryheap_test.go | 19 ++++++++++++++++++- trees/redblacktree/redblacktree_test.go | 16 +++++++++++++++- 8 files changed, 110 insertions(+), 6 deletions(-) diff --git a/lists/arraylist/arraylist_test.go b/lists/arraylist/arraylist_test.go index b4e131b..66b7499 100644 --- a/lists/arraylist/arraylist_test.go +++ b/lists/arraylist/arraylist_test.go @@ -393,6 +393,21 @@ func TestListIteratorReset(t *testing.T) { } } +func TestListIteratorLast(t *testing.T) { + list := New() + it := list.Iterator() + if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + list.Add("a", "b", "c") + if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 2 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "c") + } +} + func BenchmarkList(b *testing.B) { for i := 0; i < b.N; i++ { list := New() diff --git a/lists/doublylinkedlist/doublylinkedlist_test.go b/lists/doublylinkedlist/doublylinkedlist_test.go index e24f376..4a6b66a 100644 --- a/lists/doublylinkedlist/doublylinkedlist_test.go +++ b/lists/doublylinkedlist/doublylinkedlist_test.go @@ -393,6 +393,21 @@ func TestListIteratorReset(t *testing.T) { } } +func TestListIteratorLast(t *testing.T) { + list := New() + it := list.Iterator() + if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + list.Add("a", "b", "c") + if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 2 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "c") + } +} + func BenchmarkList(b *testing.B) { for i := 0; i < b.N; i++ { list := New() diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 228472c..76f13bf 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -406,7 +406,7 @@ func TestMapIteratorPrev(t *testing.T) { } } -func TestListIteratorReset(t *testing.T) { +func TestMapIteratorReset(t *testing.T) { m := NewWithIntComparator() it := m.Iterator() it.Reset() @@ -422,6 +422,20 @@ func TestListIteratorReset(t *testing.T) { } } +func TestMapIteratorLast(t *testing.T) { + m := NewWithIntComparator() + m.Put(3, "c") + m.Put(1, "a") + m.Put(2, "b") + it := m.Iterator() + if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if key, value := it.Key(), it.Value(); key != 3 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c") + } +} + func BenchmarkMap(b *testing.B) { for i := 0; i < b.N; i++ { m := NewWithIntComparator() diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index 990cf3c..b645eb0 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -278,7 +278,7 @@ func TestSetIteratorPrev(t *testing.T) { } } -func TestListIteratorReset(t *testing.T) { +func TestSetIteratorReset(t *testing.T) { m := NewWithStringComparator() it := m.Iterator() it.Reset() @@ -292,6 +292,18 @@ func TestListIteratorReset(t *testing.T) { } } +func TestSetIteratorLast(t *testing.T) { + set := NewWithStringComparator() + set.Add("a", "b", "c") + it := set.Iterator() + if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 3 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 3, "c") + } +} + func BenchmarkSet(b *testing.B) { for i := 0; i < b.N; i++ { set := NewWithIntComparator() diff --git a/stacks/arraystack/arraystack_test.go b/stacks/arraystack/arraystack_test.go index 89faa43..0fd2118 100644 --- a/stacks/arraystack/arraystack_test.go +++ b/stacks/arraystack/arraystack_test.go @@ -176,7 +176,7 @@ func TestStackIteratorPrev(t *testing.T) { } } -func TestListIteratorReset(t *testing.T) { +func TestStackIteratorReset(t *testing.T) { stack := New() it := stack.Iterator() it.Reset() @@ -192,6 +192,23 @@ func TestListIteratorReset(t *testing.T) { } } +func TestStackIteratorLast(t *testing.T) { + stack := New() + it := stack.Iterator() + if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + stack.Push("a") + stack.Push("b") + stack.Push("c") + if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 2 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "a") + } +} + func BenchmarkStack(b *testing.B) { for i := 0; i < b.N; i++ { stack := New() diff --git a/stacks/linkedliststack/linkedliststack_test.go b/stacks/linkedliststack/linkedliststack_test.go index f9f1df0..4283da0 100644 --- a/stacks/linkedliststack/linkedliststack_test.go +++ b/stacks/linkedliststack/linkedliststack_test.go @@ -136,7 +136,7 @@ func TestStackIterator(t *testing.T) { } } -func TestListIteratorReset(t *testing.T) { +func TestStackIteratorReset(t *testing.T) { stack := New() it := stack.Iterator() it.Reset() diff --git a/trees/binaryheap/binaryheap_test.go b/trees/binaryheap/binaryheap_test.go index aed82c0..3f925f7 100644 --- a/trees/binaryheap/binaryheap_test.go +++ b/trees/binaryheap/binaryheap_test.go @@ -191,7 +191,7 @@ func TestBinaryHeapIteratorPrev(t *testing.T) { } } -func TestListIteratorReset(t *testing.T) { +func TestBinaryHeapIteratorReset(t *testing.T) { tree := NewWithIntComparator() it := tree.Iterator() it.Reset() @@ -207,6 +207,23 @@ func TestListIteratorReset(t *testing.T) { } } +func TestBinaryHeapIteratorLast(t *testing.T) { + tree := NewWithIntComparator() + it := tree.Iterator() + if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + tree.Push(2) + tree.Push(3) + tree.Push(1) // [1,3,2](2 swapped with 1, hence last) + if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 2 || value != 2 { + t.Errorf("Got %v,%v expected %v,%v", index, value, 2, 2) + } +} + func BenchmarkBinaryHeap(b *testing.B) { for i := 0; i < b.N; i++ { heap := NewWithIntComparator() diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 3795859..9c321f1 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -496,7 +496,7 @@ func TestRedBlackTreeIterator4(t *testing.T) { } } -func TestListIteratorReset(t *testing.T) { +func TestRedBlackTreeIteratorReset(t *testing.T) { tree := NewWithIntComparator() tree.Put(3, "c") tree.Put(1, "a") @@ -512,6 +512,20 @@ func TestListIteratorReset(t *testing.T) { } } +func TestRedBlackTreeIteratorLast(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it := tree.Iterator() + if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if key, value := it.Key(), it.Value(); key != 3 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c") + } +} + func BenchmarkRedBlackTree(b *testing.B) { for i := 0; i < b.N; i++ { tree := NewWithIntComparator() From bdfeab4912b5ea8f1a853c290a7494ce89ae5547 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 26 Jun 2016 22:50:14 +0200 Subject: [PATCH 05/10] - iterator first on all structures with reversible iterators --- containers/iterator.go | 12 ++++++++++-- lists/arraylist/arraylist.go | 8 ++++++++ lists/doublylinkedlist/doublylinkedlist.go | 8 ++++++++ lists/singlylinkedlist/singlylinkedlist.go | 8 ++++++++ maps/treemap/treemap.go | 12 ++++++++++-- sets/treeset/treeset.go | 8 ++++++++ stacks/arraystack/arraystack.go | 8 ++++++++ stacks/linkedliststack/linkedliststack.go | 8 ++++++++ trees/binaryheap/binaryheap.go | 8 ++++++++ trees/redblacktree/redblacktree.go | 12 ++++++++++-- 10 files changed, 86 insertions(+), 6 deletions(-) diff --git a/containers/iterator.go b/containers/iterator.go index 9251550..144151e 100644 --- a/containers/iterator.go +++ b/containers/iterator.go @@ -42,6 +42,10 @@ type IteratorWithIndex interface { // Reset sets the iterator to the initial state. // Call Next() to fetch the first element if any. Reset() + // First moves the iterator to the first element and returns true if there was a first element in the container. + // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). + // Modifies the state of the iterator. + First() bool } // IteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs. @@ -60,6 +64,10 @@ type IteratorWithKey interface { // Reset sets the iterator to the initial state. // Call Next() to fetch the first element if any. Reset() + // First moves the iterator to the first element and returns true if there was a first element in the container. + // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). + // Modifies the state of the iterator. + First() bool } // ReverseIteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index. @@ -94,11 +102,11 @@ type ReverseIteratorWithIndex interface { // Last() function to move the iterator to the last element. type ReverseIteratorWithKey interface { // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. - // If Prev() returns true, then previous element's index and value can be retrieved by Key() and Value(). + // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. Prev() bool // Last moves the iterator to the last element and returns true if there was a last element in the container. - // If Last() returns true, then last element's index and value can be retrieved by Key() and Value(). + // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. Last() bool diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go index 17d84d7..dccfc88 100644 --- a/lists/arraylist/arraylist.go +++ b/lists/arraylist/arraylist.go @@ -230,6 +230,14 @@ func (iterator *Iterator) Reset() { iterator.index = -1 } +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) First() bool { + iterator.Reset() + return iterator.Next() +} + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. diff --git a/lists/doublylinkedlist/doublylinkedlist.go b/lists/doublylinkedlist/doublylinkedlist.go index 7ef4047..7cb6778 100644 --- a/lists/doublylinkedlist/doublylinkedlist.go +++ b/lists/doublylinkedlist/doublylinkedlist.go @@ -370,6 +370,14 @@ func (iterator *Iterator) Reset() { iterator.element = nil } +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) First() bool { + iterator.Reset() + return iterator.Next() +} + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. diff --git a/lists/singlylinkedlist/singlylinkedlist.go b/lists/singlylinkedlist/singlylinkedlist.go index 4a0eb1e..cbcf95a 100644 --- a/lists/singlylinkedlist/singlylinkedlist.go +++ b/lists/singlylinkedlist/singlylinkedlist.go @@ -323,6 +323,14 @@ func (iterator *Iterator) Reset() { iterator.element = nil } +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) First() bool { + iterator.Reset() + return iterator.Next() +} + // Each calls the given function once for each element, passing that element's index and value. func (list *List) Each(f func(index int, value interface{})) { iterator := list.Iterator() diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index 424cae6..a24e902 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -147,7 +147,7 @@ func (iterator *Iterator) Next() bool { } // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. -// If Prev() returns true, then previous element's index and value can be retrieved by Key() and Value(). +// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Prev() bool { return iterator.iterator.Prev() @@ -171,8 +171,16 @@ func (iterator *Iterator) Reset() { iterator.iterator.Reset() } +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's key and value can be retrieved by Key() and Value(). +// Modifies the state of the iterator +func (iterator *Iterator) First() bool { + iterator.Reset() + return iterator.Next() +} + // Last moves the iterator to the last element and returns true if there was a last element in the container. -// If Last() returns true, then last element's index and value can be retrieved by Key() and Value(). +// If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { return iterator.iterator.Last() diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index 46feceb..d33cb81 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -158,6 +158,14 @@ func (iterator *Iterator) Reset() { iterator.iterator.Reset() } +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) First() bool { + iterator.Reset() + return iterator.Next() +} + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. diff --git a/stacks/arraystack/arraystack.go b/stacks/arraystack/arraystack.go index ea65bdd..3539538 100644 --- a/stacks/arraystack/arraystack.go +++ b/stacks/arraystack/arraystack.go @@ -149,6 +149,14 @@ func (iterator *Iterator) Reset() { iterator.index = -1 } +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) First() bool { + iterator.Reset() + return iterator.Next() +} + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. diff --git a/stacks/linkedliststack/linkedliststack.go b/stacks/linkedliststack/linkedliststack.go index f8cd31d..8ca7579 100644 --- a/stacks/linkedliststack/linkedliststack.go +++ b/stacks/linkedliststack/linkedliststack.go @@ -134,6 +134,14 @@ func (iterator *Iterator) Reset() { iterator.index = -1 } +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) First() bool { + iterator.Reset() + return iterator.Next() +} + // String returns a string representation of container func (stack *Stack) String() string { str := "LinkedListStack\n" diff --git a/trees/binaryheap/binaryheap.go b/trees/binaryheap/binaryheap.go index e7819da..5188033 100644 --- a/trees/binaryheap/binaryheap.go +++ b/trees/binaryheap/binaryheap.go @@ -165,6 +165,14 @@ func (iterator *Iterator) Reset() { iterator.index = -1 } +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's index and value can be retrieved by Index() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) First() bool { + iterator.Reset() + return iterator.Next() +} + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index b1ab99b..69c8baf 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -319,7 +319,7 @@ func (iterator *Iterator) Next() bool { } // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. -// If Prev() returns true, then previous element's index and value can be retrieved by Key() and Value(). +// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Prev() bool { if iterator.node == nil { @@ -363,8 +363,16 @@ func (iterator *Iterator) Reset() { iterator.node = nil } +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's key and value can be retrieved by Key() and Value(). +// Modifies the state of the iterator +func (iterator *Iterator) First() bool { + iterator.Reset() + return iterator.Next() +} + // Last moves the iterator to the last element and returns true if there was a last element in the container. -// If Last() returns true, then last element's index and value can be retrieved by Key() and Value(). +// If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { iterator.node = iterator.tree.Right() From cbc23a5b79203f9a468f09a79a03b0088fc1060e Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 26 Jun 2016 23:58:23 +0200 Subject: [PATCH 06/10] - test iterator first on all iterable data structures --- lists/arraylist/arraylist_test.go | 15 +++++++++++ .../doublylinkedlist/doublylinkedlist_test.go | 15 +++++++++++ .../singlylinkedlist/singlylinkedlist_test.go | 15 +++++++++++ maps/treemap/treemap_test.go | 14 ++++++++++ sets/treeset/treeset_test.go | 12 +++++++++ stacks/arraystack/arraystack_test.go | 17 ++++++++++++ .../linkedliststack/linkedliststack_test.go | 17 ++++++++++++ trees/binaryheap/binaryheap_test.go | 27 +++++++++++++++---- trees/redblacktree/redblacktree_test.go | 14 ++++++++++ 9 files changed, 141 insertions(+), 5 deletions(-) diff --git a/lists/arraylist/arraylist_test.go b/lists/arraylist/arraylist_test.go index 66b7499..fa2ba57 100644 --- a/lists/arraylist/arraylist_test.go +++ b/lists/arraylist/arraylist_test.go @@ -393,6 +393,21 @@ func TestListIteratorReset(t *testing.T) { } } +func TestListIteratorFirst(t *testing.T) { + list := New() + it := list.Iterator() + if actualValue, expectedValue := it.First(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + list.Add("a", "b", "c") + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 0 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") + } +} + func TestListIteratorLast(t *testing.T) { list := New() it := list.Iterator() diff --git a/lists/doublylinkedlist/doublylinkedlist_test.go b/lists/doublylinkedlist/doublylinkedlist_test.go index 4a6b66a..fd8495d 100644 --- a/lists/doublylinkedlist/doublylinkedlist_test.go +++ b/lists/doublylinkedlist/doublylinkedlist_test.go @@ -393,6 +393,21 @@ func TestListIteratorReset(t *testing.T) { } } +func TestListIteratorFirst(t *testing.T) { + list := New() + it := list.Iterator() + if actualValue, expectedValue := it.First(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + list.Add("a", "b", "c") + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 0 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") + } +} + func TestListIteratorLast(t *testing.T) { list := New() it := list.Iterator() diff --git a/lists/singlylinkedlist/singlylinkedlist_test.go b/lists/singlylinkedlist/singlylinkedlist_test.go index 6c0241d..c313347 100644 --- a/lists/singlylinkedlist/singlylinkedlist_test.go +++ b/lists/singlylinkedlist/singlylinkedlist_test.go @@ -352,6 +352,21 @@ func TestListIteratorReset(t *testing.T) { } } +func TestListIteratorFirst(t *testing.T) { + list := New() + it := list.Iterator() + if actualValue, expectedValue := it.First(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + list.Add("a", "b", "c") + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 0 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") + } +} + func BenchmarkList(b *testing.B) { for i := 0; i < b.N; i++ { list := New() diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 76f13bf..2a4f82d 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -422,6 +422,20 @@ func TestMapIteratorReset(t *testing.T) { } } +func TestMapIteratorFirst(t *testing.T) { + m := NewWithIntComparator() + m.Put(3, "c") + m.Put(1, "a") + m.Put(2, "b") + it := m.Iterator() + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if key, value := it.Key(), it.Value(); key != 1 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") + } +} + func TestMapIteratorLast(t *testing.T) { m := NewWithIntComparator() m.Put(3, "c") diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index b645eb0..c419a6b 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -292,6 +292,18 @@ func TestSetIteratorReset(t *testing.T) { } } +func TestSetIteratorFirst(t *testing.T) { + set := NewWithStringComparator() + set.Add("a", "b", "c") + it := set.Iterator() + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 0 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") + } +} + func TestSetIteratorLast(t *testing.T) { set := NewWithStringComparator() set.Add("a", "b", "c") diff --git a/stacks/arraystack/arraystack_test.go b/stacks/arraystack/arraystack_test.go index 0fd2118..b744bc1 100644 --- a/stacks/arraystack/arraystack_test.go +++ b/stacks/arraystack/arraystack_test.go @@ -192,6 +192,23 @@ func TestStackIteratorReset(t *testing.T) { } } +func TestStackIteratorFirst(t *testing.T) { + stack := New() + it := stack.Iterator() + if actualValue, expectedValue := it.First(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + stack.Push("a") + stack.Push("b") + stack.Push("c") + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 0 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") + } +} + func TestStackIteratorLast(t *testing.T) { stack := New() it := stack.Iterator() diff --git a/stacks/linkedliststack/linkedliststack_test.go b/stacks/linkedliststack/linkedliststack_test.go index 4283da0..ce97b8a 100644 --- a/stacks/linkedliststack/linkedliststack_test.go +++ b/stacks/linkedliststack/linkedliststack_test.go @@ -152,6 +152,23 @@ func TestStackIteratorReset(t *testing.T) { } } +func TestStackIteratorFirst(t *testing.T) { + stack := New() + it := stack.Iterator() + if actualValue, expectedValue := it.First(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + stack.Push("a") + stack.Push("b") + stack.Push("c") + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 0 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") + } +} + func BenchmarkStack(b *testing.B) { for i := 0; i < b.N; i++ { stack := New() diff --git a/trees/binaryheap/binaryheap_test.go b/trees/binaryheap/binaryheap_test.go index 3f925f7..17311a3 100644 --- a/trees/binaryheap/binaryheap_test.go +++ b/trees/binaryheap/binaryheap_test.go @@ -192,12 +192,12 @@ func TestBinaryHeapIteratorPrev(t *testing.T) { } func TestBinaryHeapIteratorReset(t *testing.T) { - tree := NewWithIntComparator() - it := tree.Iterator() + heap := NewWithIntComparator() + it := heap.Iterator() it.Reset() - tree.Push(2) - tree.Push(3) - tree.Push(1) + heap.Push(2) + heap.Push(3) + heap.Push(1) for it.Next() { } it.Reset() @@ -207,6 +207,23 @@ func TestBinaryHeapIteratorReset(t *testing.T) { } } +func TestStackIteratorFirst(t *testing.T) { + heap := NewWithIntComparator() + it := heap.Iterator() + if actualValue, expectedValue := it.First(), false; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + heap.Push(3) // [3] + heap.Push(2) // [2,3] + heap.Push(1) // [1,3,2](2 swapped with 1, hence last) + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if index, value := it.Index(), it.Value(); index != 0 || value != 1 { + t.Errorf("Got %v,%v expected %v,%v", index, value, 0, 1) + } +} + func TestBinaryHeapIteratorLast(t *testing.T) { tree := NewWithIntComparator() it := tree.Iterator() diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 9c321f1..495b68e 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -512,6 +512,20 @@ func TestRedBlackTreeIteratorReset(t *testing.T) { } } +func TestRedBlackTreeIteratorFirst(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it := tree.Iterator() + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if key, value := it.Key(), it.Value(); key != 1 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") + } +} + func TestRedBlackTreeIteratorLast(t *testing.T) { tree := NewWithIntComparator() tree.Put(3, "c") From 57162feff5d4a7f343b131008eaab85e8732b74b Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 27 Jun 2016 00:08:01 +0200 Subject: [PATCH 07/10] - rename Reset() to Begin() in iterators (this will allow End() which will make reverse loops more readable) --- containers/iterator.go | 18 ++++++++++++++---- lists/arraylist/arraylist.go | 6 +++--- lists/arraylist/arraylist_test.go | 6 +++--- lists/doublylinkedlist/doublylinkedlist.go | 6 +++--- .../doublylinkedlist/doublylinkedlist_test.go | 6 +++--- lists/singlylinkedlist/singlylinkedlist.go | 6 +++--- .../singlylinkedlist/singlylinkedlist_test.go | 6 +++--- maps/treemap/treemap.go | 8 ++++---- maps/treemap/treemap_test.go | 6 +++--- sets/treeset/treeset.go | 8 ++++---- sets/treeset/treeset_test.go | 6 +++--- stacks/arraystack/arraystack.go | 6 +++--- stacks/arraystack/arraystack_test.go | 6 +++--- stacks/linkedliststack/linkedliststack.go | 6 +++--- stacks/linkedliststack/linkedliststack_test.go | 6 +++--- trees/binaryheap/binaryheap.go | 6 +++--- trees/binaryheap/binaryheap_test.go | 6 +++--- trees/redblacktree/redblacktree.go | 6 +++--- trees/redblacktree/redblacktree_test.go | 6 +++--- 19 files changed, 70 insertions(+), 60 deletions(-) diff --git a/containers/iterator.go b/containers/iterator.go index 144151e..1bd7b0e 100644 --- a/containers/iterator.go +++ b/containers/iterator.go @@ -33,15 +33,19 @@ type IteratorWithIndex interface { // If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. Next() bool + // Value returns the current element's value. // Does not modify the state of the iterator. Value() interface{} + // Index returns the current element's index. // Does not modify the state of the iterator. Index() int - // Reset sets the iterator to the initial state. + + // Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. - Reset() + Begin() + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -55,15 +59,19 @@ type IteratorWithKey interface { // If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. Next() bool + // Value returns the current element's value. // Does not modify the state of the iterator. Value() interface{} + // Key returns the current element's key. // Does not modify the state of the iterator. Key() interface{} - // Reset sets the iterator to the initial state. + + // Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. - Reset() + Begin() + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. @@ -82,6 +90,7 @@ type ReverseIteratorWithIndex interface { // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. Prev() bool + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -105,6 +114,7 @@ type ReverseIteratorWithKey interface { // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. Prev() bool + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go index dccfc88..57eca3c 100644 --- a/lists/arraylist/arraylist.go +++ b/lists/arraylist/arraylist.go @@ -224,9 +224,9 @@ func (iterator *Iterator) Index() int { return iterator.index } -// Reset sets the iterator to the initial state. +// Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. -func (iterator *Iterator) Reset() { +func (iterator *Iterator) Begin() { iterator.index = -1 } @@ -234,7 +234,7 @@ func (iterator *Iterator) Reset() { // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) First() bool { - iterator.Reset() + iterator.Begin() return iterator.Next() } diff --git a/lists/arraylist/arraylist_test.go b/lists/arraylist/arraylist_test.go index fa2ba57..f87cfe9 100644 --- a/lists/arraylist/arraylist_test.go +++ b/lists/arraylist/arraylist_test.go @@ -379,14 +379,14 @@ func TestListIteratorPrev(t *testing.T) { } } -func TestListIteratorReset(t *testing.T) { +func TestListIteratorBegin(t *testing.T) { list := New() it := list.Iterator() - it.Reset() + it.Begin() list.Add("a", "b", "c") for it.Next() { } - it.Reset() + it.Begin() it.Next() if index, value := it.Index(), it.Value(); index != 0 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") diff --git a/lists/doublylinkedlist/doublylinkedlist.go b/lists/doublylinkedlist/doublylinkedlist.go index 7cb6778..2f5bb2e 100644 --- a/lists/doublylinkedlist/doublylinkedlist.go +++ b/lists/doublylinkedlist/doublylinkedlist.go @@ -363,9 +363,9 @@ func (iterator *Iterator) Index() int { return iterator.index } -// Reset sets the iterator to the initial state. +// Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. -func (iterator *Iterator) Reset() { +func (iterator *Iterator) Begin() { iterator.index = -1 iterator.element = nil } @@ -374,7 +374,7 @@ func (iterator *Iterator) Reset() { // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) First() bool { - iterator.Reset() + iterator.Begin() return iterator.Next() } diff --git a/lists/doublylinkedlist/doublylinkedlist_test.go b/lists/doublylinkedlist/doublylinkedlist_test.go index fd8495d..621c750 100644 --- a/lists/doublylinkedlist/doublylinkedlist_test.go +++ b/lists/doublylinkedlist/doublylinkedlist_test.go @@ -379,14 +379,14 @@ func TestListIteratorPrev(t *testing.T) { } } -func TestListIteratorReset(t *testing.T) { +func TestListIteratorBegin(t *testing.T) { list := New() it := list.Iterator() - it.Reset() + it.Begin() list.Add("a", "b", "c") for it.Next() { } - it.Reset() + it.Begin() it.Next() if index, value := it.Index(), it.Value(); index != 0 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") diff --git a/lists/singlylinkedlist/singlylinkedlist.go b/lists/singlylinkedlist/singlylinkedlist.go index cbcf95a..41db255 100644 --- a/lists/singlylinkedlist/singlylinkedlist.go +++ b/lists/singlylinkedlist/singlylinkedlist.go @@ -316,9 +316,9 @@ func (iterator *Iterator) Index() int { return iterator.index } -// Reset sets the iterator to the initial state. +// Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. -func (iterator *Iterator) Reset() { +func (iterator *Iterator) Begin() { iterator.index = -1 iterator.element = nil } @@ -327,7 +327,7 @@ func (iterator *Iterator) Reset() { // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) First() bool { - iterator.Reset() + iterator.Begin() return iterator.Next() } diff --git a/lists/singlylinkedlist/singlylinkedlist_test.go b/lists/singlylinkedlist/singlylinkedlist_test.go index c313347..03f9b2d 100644 --- a/lists/singlylinkedlist/singlylinkedlist_test.go +++ b/lists/singlylinkedlist/singlylinkedlist_test.go @@ -338,14 +338,14 @@ func TestListIteratorNext(t *testing.T) { } } -func TestListIteratorReset(t *testing.T) { +func TestListIteratorBegin(t *testing.T) { list := New() it := list.Iterator() - it.Reset() + it.Begin() list.Add("a", "b", "c") for it.Next() { } - it.Reset() + it.Begin() it.Next() if index, value := it.Index(), it.Value(); index != 0 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index a24e902..1b531ee 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -165,17 +165,17 @@ func (iterator *Iterator) Key() interface{} { return iterator.iterator.Key() } -// Reset sets the iterator to the initial state. +// Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. -func (iterator *Iterator) Reset() { - iterator.iterator.Reset() +func (iterator *Iterator) Begin() { + iterator.iterator.Begin() } // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator func (iterator *Iterator) First() bool { - iterator.Reset() + iterator.Begin() return iterator.Next() } diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 2a4f82d..8b0857a 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -406,16 +406,16 @@ func TestMapIteratorPrev(t *testing.T) { } } -func TestMapIteratorReset(t *testing.T) { +func TestMapIteratorBegin(t *testing.T) { m := NewWithIntComparator() it := m.Iterator() - it.Reset() + it.Begin() m.Put(3, "c") m.Put(1, "a") m.Put(2, "b") for it.Next() { } - it.Reset() + it.Begin() it.Next() if key, value := it.Key(), it.Value(); key != 1 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index d33cb81..8acd804 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -151,18 +151,18 @@ func (iterator *Iterator) Index() int { return iterator.index } -// Reset sets the iterator to the initial state. +// Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. -func (iterator *Iterator) Reset() { +func (iterator *Iterator) Begin() { iterator.index = -1 - iterator.iterator.Reset() + iterator.iterator.Begin() } // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) First() bool { - iterator.Reset() + iterator.Begin() return iterator.Next() } diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index c419a6b..a2a78fe 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -278,14 +278,14 @@ func TestSetIteratorPrev(t *testing.T) { } } -func TestSetIteratorReset(t *testing.T) { +func TestSetIteratorBegin(t *testing.T) { m := NewWithStringComparator() it := m.Iterator() - it.Reset() + it.Begin() m.Add("a", "b", "c") for it.Next() { } - it.Reset() + it.Begin() it.Next() if index, value := it.Index(), it.Value(); index != 0 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a") diff --git a/stacks/arraystack/arraystack.go b/stacks/arraystack/arraystack.go index 3539538..81f6837 100644 --- a/stacks/arraystack/arraystack.go +++ b/stacks/arraystack/arraystack.go @@ -143,9 +143,9 @@ func (iterator *Iterator) Index() int { return iterator.index } -// Reset sets the iterator to the initial state. +// Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. -func (iterator *Iterator) Reset() { +func (iterator *Iterator) Begin() { iterator.index = -1 } @@ -153,7 +153,7 @@ func (iterator *Iterator) Reset() { // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) First() bool { - iterator.Reset() + iterator.Begin() return iterator.Next() } diff --git a/stacks/arraystack/arraystack_test.go b/stacks/arraystack/arraystack_test.go index b744bc1..bb68e97 100644 --- a/stacks/arraystack/arraystack_test.go +++ b/stacks/arraystack/arraystack_test.go @@ -176,16 +176,16 @@ func TestStackIteratorPrev(t *testing.T) { } } -func TestStackIteratorReset(t *testing.T) { +func TestStackIteratorBegin(t *testing.T) { stack := New() it := stack.Iterator() - it.Reset() + it.Begin() stack.Push("a") stack.Push("b") stack.Push("c") for it.Next() { } - it.Reset() + it.Begin() it.Next() if index, value := it.Index(), it.Value(); index != 0 || value != "c" { t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") diff --git a/stacks/linkedliststack/linkedliststack.go b/stacks/linkedliststack/linkedliststack.go index 8ca7579..0778f6d 100644 --- a/stacks/linkedliststack/linkedliststack.go +++ b/stacks/linkedliststack/linkedliststack.go @@ -128,9 +128,9 @@ func (iterator *Iterator) Index() int { return iterator.index } -// Reset sets the iterator to the initial state. +// Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. -func (iterator *Iterator) Reset() { +func (iterator *Iterator) Begin() { iterator.index = -1 } @@ -138,7 +138,7 @@ func (iterator *Iterator) Reset() { // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) First() bool { - iterator.Reset() + iterator.Begin() return iterator.Next() } diff --git a/stacks/linkedliststack/linkedliststack_test.go b/stacks/linkedliststack/linkedliststack_test.go index ce97b8a..ec218cb 100644 --- a/stacks/linkedliststack/linkedliststack_test.go +++ b/stacks/linkedliststack/linkedliststack_test.go @@ -136,16 +136,16 @@ func TestStackIterator(t *testing.T) { } } -func TestStackIteratorReset(t *testing.T) { +func TestStackIteratorBegin(t *testing.T) { stack := New() it := stack.Iterator() - it.Reset() + it.Begin() stack.Push("a") stack.Push("b") stack.Push("c") for it.Next() { } - it.Reset() + it.Begin() it.Next() if index, value := it.Index(), it.Value(); index != 0 || value != "c" { t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") diff --git a/trees/binaryheap/binaryheap.go b/trees/binaryheap/binaryheap.go index 5188033..fc62d79 100644 --- a/trees/binaryheap/binaryheap.go +++ b/trees/binaryheap/binaryheap.go @@ -159,9 +159,9 @@ func (iterator *Iterator) Index() int { return iterator.index } -// Reset sets the iterator to the initial state. +// Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. -func (iterator *Iterator) Reset() { +func (iterator *Iterator) Begin() { iterator.index = -1 } @@ -169,7 +169,7 @@ func (iterator *Iterator) Reset() { // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) First() bool { - iterator.Reset() + iterator.Begin() return iterator.Next() } diff --git a/trees/binaryheap/binaryheap_test.go b/trees/binaryheap/binaryheap_test.go index 17311a3..83658ff 100644 --- a/trees/binaryheap/binaryheap_test.go +++ b/trees/binaryheap/binaryheap_test.go @@ -191,16 +191,16 @@ func TestBinaryHeapIteratorPrev(t *testing.T) { } } -func TestBinaryHeapIteratorReset(t *testing.T) { +func TestBinaryHeapIteratorBegin(t *testing.T) { heap := NewWithIntComparator() it := heap.Iterator() - it.Reset() + it.Begin() heap.Push(2) heap.Push(3) heap.Push(1) for it.Next() { } - it.Reset() + it.Begin() it.Next() if index, value := it.Index(), it.Value(); index != 0 || value != 1 { t.Errorf("Got %v,%v expected %v,%v", index, value, 0, 1) diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index 69c8baf..134c74e 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -357,9 +357,9 @@ func (iterator *Iterator) Key() interface{} { return iterator.node.Key } -// Reset sets the iterator to the initial state. +// Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. -func (iterator *Iterator) Reset() { +func (iterator *Iterator) Begin() { iterator.node = nil } @@ -367,7 +367,7 @@ func (iterator *Iterator) Reset() { // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator func (iterator *Iterator) First() bool { - iterator.Reset() + iterator.Begin() return iterator.Next() } diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 495b68e..ab2946a 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -496,16 +496,16 @@ func TestRedBlackTreeIterator4(t *testing.T) { } } -func TestRedBlackTreeIteratorReset(t *testing.T) { +func TestRedBlackTreeIteratorBegin(t *testing.T) { tree := NewWithIntComparator() tree.Put(3, "c") tree.Put(1, "a") tree.Put(2, "b") it := tree.Iterator() - it.Reset() + it.Begin() for it.Next() { } - it.Reset() + it.Begin() it.Next() if key, value := it.Key(), it.Value(); key != 1 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") From f052c960692e1691068c742cb2651155cfecb883 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 27 Jun 2016 00:41:32 +0200 Subject: [PATCH 08/10] - iterator end on reverse-iterable data structures --- containers/iterator.go | 16 ++++--- examples/main/iteratorwithindex.go | 55 ++++++++++++++++++++++ lists/arraylist/arraylist.go | 8 +++- lists/doublylinkedlist/doublylinkedlist.go | 10 +++- maps/treemap/treemap.go | 9 +++- sets/treeset/treeset.go | 9 +++- stacks/arraystack/arraystack.go | 8 +++- trees/binaryheap/binaryheap.go | 8 +++- trees/redblacktree/redblacktree.go | 11 ++++- 9 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 examples/main/iteratorwithindex.go diff --git a/containers/iterator.go b/containers/iterator.go index 1bd7b0e..5692982 100644 --- a/containers/iterator.go +++ b/containers/iterator.go @@ -85,21 +85,24 @@ type IteratorWithKey interface { // Prev() function to enable traversal in reverse // // Last() function to move the iterator to the last element. +// +// End() function to move the iterator past the last element (one-past-the-end). type ReverseIteratorWithIndex interface { // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. Prev() bool + // End moves the iterator past the last element (one-past-the-end). + // Call Prev() to fetch the last element if any. + End() + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. Last() bool IteratorWithIndex - // Next() bool - // Value() interface{} - // Index() int } // ReverseIteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs. @@ -115,13 +118,14 @@ type ReverseIteratorWithKey interface { // Modifies the state of the iterator. Prev() bool + // End moves the iterator past the last element (one-past-the-end). + // Call Prev() to fetch the last element if any. + End() + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. Last() bool IteratorWithKey - // Next() bool - // Value() interface{} - // Key() interface{} } diff --git a/examples/main/iteratorwithindex.go b/examples/main/iteratorwithindex.go new file mode 100644 index 0000000..6b715d4 --- /dev/null +++ b/examples/main/iteratorwithindex.go @@ -0,0 +1,55 @@ +/* +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 main + +import ( + "fmt" + "github.com/emirpasic/gods/sets/treeset" +) + +// IteratorWithIndexExample to demonstrate basic usage of IteratorWithIndex +//func IteratorWithIndexExample() { +func main() { + set := treeset.NewWithIntComparator() + set.Add(1, 2, 3) + + // Forward iteration + it := set.Iterator() + for it.Next() { + index, value := it.Index(), it.Value() + fmt.Println("Index: ", index, "Value: ", value) + } + + // Backward iteration (reverse) + for it.Last(); ; { + index, value := it.Index(), it.Value() + fmt.Println("Index: ", index, "Value: ", value) + if !it.Prev() { + break + } + } +} diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go index 57eca3c..4e44d4a 100644 --- a/lists/arraylist/arraylist.go +++ b/lists/arraylist/arraylist.go @@ -230,6 +230,12 @@ func (iterator *Iterator) Begin() { iterator.index = -1 } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.list.size +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -242,7 +248,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.list.size + iterator.End() return iterator.Prev() } diff --git a/lists/doublylinkedlist/doublylinkedlist.go b/lists/doublylinkedlist/doublylinkedlist.go index 2f5bb2e..184db76 100644 --- a/lists/doublylinkedlist/doublylinkedlist.go +++ b/lists/doublylinkedlist/doublylinkedlist.go @@ -370,6 +370,13 @@ func (iterator *Iterator) Begin() { iterator.element = nil } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.list.size + iterator.element = iterator.list.last +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -382,8 +389,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.list.size - iterator.element = iterator.list.last + iterator.End() return iterator.Prev() } diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index 1b531ee..995d25b 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -171,12 +171,17 @@ func (iterator *Iterator) Begin() { iterator.iterator.Begin() } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.iterator.End() +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator func (iterator *Iterator) First() bool { - iterator.Begin() - return iterator.Next() + return iterator.iterator.First() } // Last moves the iterator to the last element and returns true if there was a last element in the container. diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index 8acd804..6651bae 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -158,6 +158,13 @@ func (iterator *Iterator) Begin() { iterator.iterator.Begin() } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.tree.Size() + iterator.iterator.End() +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -170,7 +177,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.tree.Size() + iterator.End() return iterator.iterator.Last() } diff --git a/stacks/arraystack/arraystack.go b/stacks/arraystack/arraystack.go index 81f6837..ee7cc82 100644 --- a/stacks/arraystack/arraystack.go +++ b/stacks/arraystack/arraystack.go @@ -149,6 +149,12 @@ func (iterator *Iterator) Begin() { iterator.index = -1 } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.stack.Size() +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -161,7 +167,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.stack.Size() + iterator.End() return iterator.Prev() } diff --git a/trees/binaryheap/binaryheap.go b/trees/binaryheap/binaryheap.go index fc62d79..4845c31 100644 --- a/trees/binaryheap/binaryheap.go +++ b/trees/binaryheap/binaryheap.go @@ -165,6 +165,12 @@ func (iterator *Iterator) Begin() { iterator.index = -1 } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.heap.Size() +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -177,7 +183,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.heap.Size() + iterator.End() return iterator.Prev() } diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index 134c74e..323cfac 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -363,6 +363,13 @@ func (iterator *Iterator) Begin() { iterator.node = nil } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + right := iterator.tree.Right() // ugly hack (TODO: use flags) + iterator.node = &Node{Parent: right, Key: right.Key} +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator @@ -375,8 +382,8 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.node = iterator.tree.Right() - return iterator.node != nil + iterator.End() + return iterator.Prev() } // String returns a string representation of container From 02f40db0cf90447cb1af3f00c10e2f2eedeb2eac Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 27 Jun 2016 02:42:05 +0200 Subject: [PATCH 09/10] - test iterator end on reverse-iterable data structures - fix red-black tree --- lists/arraylist/arraylist_test.go | 25 +++++++ .../doublylinkedlist/doublylinkedlist_test.go | 25 +++++++ maps/treemap/treemap_test.go | 18 ++++- sets/treeset/treeset_test.go | 25 +++++++ stacks/arraystack/arraystack_test.go | 27 ++++++++ trees/binaryheap/binaryheap_test.go | 27 ++++++++ trees/redblacktree/redblacktree.go | 69 ++++++++++++++----- trees/redblacktree/redblacktree_test.go | 65 +++++++++++++---- 8 files changed, 249 insertions(+), 32 deletions(-) diff --git a/lists/arraylist/arraylist_test.go b/lists/arraylist/arraylist_test.go index f87cfe9..daf8a16 100644 --- a/lists/arraylist/arraylist_test.go +++ b/lists/arraylist/arraylist_test.go @@ -393,6 +393,31 @@ func TestListIteratorBegin(t *testing.T) { } } +func TestListIteratorEnd(t *testing.T) { + list := New() + it := list.Iterator() + + if index := it.Index(); index != -1 { + t.Errorf("Got %v expected %v", index, -1) + } + + it.End() + if index := it.Index(); index != 0 { + t.Errorf("Got %v expected %v", index, 0) + } + + list.Add("a", "b", "c") + it.End() + if index := it.Index(); index != list.Size() { + t.Errorf("Got %v expected %v", index, list.Size()) + } + + it.Prev() + if index, value := it.Index(), it.Value(); index != list.Size()-1 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, list.Size()-1, "c") + } +} + func TestListIteratorFirst(t *testing.T) { list := New() it := list.Iterator() diff --git a/lists/doublylinkedlist/doublylinkedlist_test.go b/lists/doublylinkedlist/doublylinkedlist_test.go index 621c750..8cd9e96 100644 --- a/lists/doublylinkedlist/doublylinkedlist_test.go +++ b/lists/doublylinkedlist/doublylinkedlist_test.go @@ -393,6 +393,31 @@ func TestListIteratorBegin(t *testing.T) { } } +func TestListIteratorEnd(t *testing.T) { + list := New() + it := list.Iterator() + + if index := it.Index(); index != -1 { + t.Errorf("Got %v expected %v", index, -1) + } + + it.End() + if index := it.Index(); index != 0 { + t.Errorf("Got %v expected %v", index, 0) + } + + list.Add("a", "b", "c") + it.End() + if index := it.Index(); index != list.Size() { + t.Errorf("Got %v expected %v", index, list.Size()) + } + + it.Prev() + if index, value := it.Index(), it.Value(); index != list.Size()-1 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, list.Size()-1, "c") + } +} + func TestListIteratorFirst(t *testing.T) { list := New() it := list.Iterator() diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 8b0857a..b896f36 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -377,7 +377,6 @@ func TestMapIteratorPrev(t *testing.T) { } countDown := m.Size() for it.Prev() { - countDown-- key := it.Key() value := it.Value() switch key { @@ -399,9 +398,9 @@ func TestMapIteratorPrev(t *testing.T) { if actualValue, expectedValue := value, countDown; actualValue != expectedValue { t.Errorf("Got %v expected %v", actualValue, expectedValue) } + countDown-- } - // one less that in Next(), thus "1" - if actualValue, expectedValue := countDown, 1; actualValue != expectedValue { + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { t.Errorf("Got %v expected %v", actualValue, expectedValue) } } @@ -422,6 +421,19 @@ func TestMapIteratorBegin(t *testing.T) { } } +func TestMapTreeIteratorEnd(t *testing.T) { + m := NewWithIntComparator() + it := m.Iterator() + m.Put(3, "c") + m.Put(1, "a") + m.Put(2, "b") + it.End() + it.Prev() + if key, value := it.Key(), it.Value(); key != 3 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c") + } +} + func TestMapIteratorFirst(t *testing.T) { m := NewWithIntComparator() m.Put(3, "c") diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index a2a78fe..c0d21af 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -292,6 +292,31 @@ func TestSetIteratorBegin(t *testing.T) { } } +func TestSetIteratorEnd(t *testing.T) { + set := NewWithStringComparator() + it := set.Iterator() + + if index := it.Index(); index != -1 { + t.Errorf("Got %v expected %v", index, -1) + } + + it.End() + if index := it.Index(); index != 0 { + t.Errorf("Got %v expected %v", index, 0) + } + + set.Add("a", "b", "c") + it.End() + if index := it.Index(); index != set.Size() { + t.Errorf("Got %v expected %v", index, set.Size()) + } + + it.Prev() + if index, value := it.Index(), it.Value(); index != set.Size()-1 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", index, value, set.Size()-1, "c") + } +} + func TestSetIteratorFirst(t *testing.T) { set := NewWithStringComparator() set.Add("a", "b", "c") diff --git a/stacks/arraystack/arraystack_test.go b/stacks/arraystack/arraystack_test.go index bb68e97..ed27db0 100644 --- a/stacks/arraystack/arraystack_test.go +++ b/stacks/arraystack/arraystack_test.go @@ -192,6 +192,33 @@ func TestStackIteratorBegin(t *testing.T) { } } +func TestStackIteratorEnd(t *testing.T) { + stack := New() + it := stack.Iterator() + + if index := it.Index(); index != -1 { + t.Errorf("Got %v expected %v", index, -1) + } + + it.End() + if index := it.Index(); index != 0 { + t.Errorf("Got %v expected %v", index, 0) + } + + stack.Push("a") + stack.Push("b") + stack.Push("c") + it.End() + if index := it.Index(); index != stack.Size() { + t.Errorf("Got %v expected %v", index, stack.Size()) + } + + it.Prev() + if index, value := it.Index(), it.Value(); index != stack.Size()-1 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", index, value, stack.Size()-1, "a") + } +} + func TestStackIteratorFirst(t *testing.T) { stack := New() it := stack.Iterator() diff --git a/trees/binaryheap/binaryheap_test.go b/trees/binaryheap/binaryheap_test.go index 83658ff..916f9e5 100644 --- a/trees/binaryheap/binaryheap_test.go +++ b/trees/binaryheap/binaryheap_test.go @@ -207,6 +207,33 @@ func TestBinaryHeapIteratorBegin(t *testing.T) { } } +func TestListIteratorEnd(t *testing.T) { + heap := NewWithIntComparator() + it := heap.Iterator() + + if index := it.Index(); index != -1 { + t.Errorf("Got %v expected %v", index, -1) + } + + it.End() + if index := it.Index(); index != 0 { + t.Errorf("Got %v expected %v", index, 0) + } + + heap.Push(3) // [3] + heap.Push(2) // [2,3] + heap.Push(1) // [1,3,2](2 swapped with 1, hence last) + it.End() + if index := it.Index(); index != heap.Size() { + t.Errorf("Got %v expected %v", index, heap.Size()) + } + + it.Prev() + if index, value := it.Index(), it.Value(); index != heap.Size()-1 || value != 2 { + t.Errorf("Got %v,%v expected %v,%v", index, value, heap.Size()-1, 2) + } +} + func TestStackIteratorFirst(t *testing.T) { heap := NewWithIntComparator() it := heap.Iterator() diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index 323cfac..7d6f083 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -280,13 +280,20 @@ func (tree *Tree) Clear() { // Iterator holding the iterator's state type Iterator struct { - tree *Tree - node *Node + tree *Tree + node *Node + position position } +type position byte + +const ( + begin, between, end position = 0, 1, 2 +) + // Iterator returns a stateful iterator whose elements are key/value pairs. func (tree *Tree) Iterator() Iterator { - return Iterator{tree: tree, node: nil} + return Iterator{tree: tree, node: nil, position: begin} } // Next moves the iterator to the next element and returns true if there was a next element in the container. @@ -294,55 +301,84 @@ func (tree *Tree) Iterator() Iterator { // If Next() was called for the first time, then it will point the iterator to the first element if it exists. // Modifies the state of the iterator. func (iterator *Iterator) Next() bool { - if iterator.node == nil { - iterator.node = iterator.tree.Left() - return iterator.node != nil + if iterator.position == end { + goto end + } + if iterator.position == begin { + left := iterator.tree.Left() + if left == nil { + goto end + } + iterator.node = left + goto between } if iterator.node.Right != nil { iterator.node = iterator.node.Right for iterator.node.Left != nil { iterator.node = iterator.node.Left } - return true + goto between } if iterator.node.Parent != nil { node := iterator.node for iterator.node.Parent != nil { iterator.node = iterator.node.Parent if iterator.tree.Comparator(node.Key, iterator.node.Key) <= 0 { - return true + goto between } } - iterator.node = node // fix: if parent didn't satisfy the comparator criteria } + +end: + iterator.node = nil + iterator.position = end return false + +between: + iterator.position = between + return true } // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Prev() bool { - if iterator.node == nil { - return false + if iterator.position == begin { + goto begin + } + if iterator.position == end { + right := iterator.tree.Right() + if right == nil { + goto begin + } + iterator.node = right + goto between } if iterator.node.Left != nil { iterator.node = iterator.node.Left for iterator.node.Right != nil { iterator.node = iterator.node.Right } - return true + goto between } if iterator.node.Parent != nil { node := iterator.node for iterator.node.Parent != nil { iterator.node = iterator.node.Parent if iterator.tree.Comparator(node.Key, iterator.node.Key) >= 0 { - return true + goto between } } - iterator.node = node // fix: if parent didn't satisfy the comparator criteria } + +begin: + iterator.node = nil + iterator.position = begin return false + +between: + iterator.position = between + return true } // Value returns the current element's value. @@ -361,13 +397,14 @@ func (iterator *Iterator) Key() interface{} { // Call Next() to fetch the first element if any. func (iterator *Iterator) Begin() { iterator.node = nil + iterator.position = begin } // End moves the iterator past the last element (one-past-the-end). // Call Prev() to fetch the last element if any. func (iterator *Iterator) End() { - right := iterator.tree.Right() // ugly hack (TODO: use flags) - iterator.node = &Node{Parent: right, Key: right.Key} + iterator.node = nil + iterator.position = end } // First moves the iterator to the first element and returns true if there was a first element in the container. diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index ab2946a..3cc5487 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -282,7 +282,6 @@ func TestRedBlackTreeIterator1Prev(t *testing.T) { } countDown := tree.size for it.Prev() { - countDown-- key := it.Key() switch key { case countDown: @@ -294,9 +293,9 @@ func TestRedBlackTreeIterator1Prev(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, expectedValue) } } + countDown-- } - // one less that in Next(), thus "1" - if actualValue, expectedValue := countDown, 1; actualValue != expectedValue { + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) } } @@ -337,7 +336,6 @@ func TestRedBlackTreeIterator2Prev(t *testing.T) { } countDown := tree.size for it.Prev() { - countDown-- key := it.Key() switch key { case countDown: @@ -349,9 +347,9 @@ func TestRedBlackTreeIterator2Prev(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, expectedValue) } } + countDown-- } - // one less that in Next(), thus "1" - if actualValue, expectedValue := countDown, 1; actualValue != expectedValue { + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) } } @@ -388,7 +386,6 @@ func TestRedBlackTreeIterator3Prev(t *testing.T) { } countDown := tree.size for it.Prev() { - countDown-- key := it.Key() switch key { case countDown: @@ -400,9 +397,9 @@ func TestRedBlackTreeIterator3Prev(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, expectedValue) } } + countDown-- } - // one less that in Next(), thus "1" - if actualValue, expectedValue := countDown, 1; actualValue != expectedValue { + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) } } @@ -450,7 +447,7 @@ func TestRedBlackTreeIterator4Next(t *testing.T) { } } -func TestRedBlackTreeIterator4(t *testing.T) { +func TestRedBlackTreeIterator4Prev(t *testing.T) { tree := NewWithIntComparator() tree.Put(13, 5) tree.Put(8, 3) @@ -477,7 +474,6 @@ func TestRedBlackTreeIterator4(t *testing.T) { for it.Next() { } for it.Prev() { - count-- value := it.Value() switch value { case count: @@ -489,9 +485,9 @@ func TestRedBlackTreeIterator4(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, expectedValue) } } + count-- } - // one less that in Next(), thus "1" - if actualValue, expectedValue := count, 1; actualValue != expectedValue { + if actualValue, expectedValue := count, 0; actualValue != expectedValue { t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) } } @@ -502,16 +498,59 @@ func TestRedBlackTreeIteratorBegin(t *testing.T) { tree.Put(1, "a") tree.Put(2, "b") it := tree.Iterator() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + it.Begin() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + for it.Next() { } + it.Begin() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + it.Next() if key, value := it.Key(), it.Value(); key != 1 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") } } +func TestRedBlackTreeIteratorEnd(t *testing.T) { + tree := NewWithIntComparator() + it := tree.Iterator() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.End() + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it.End() + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.Prev() + if key, value := it.Key(), it.Value(); key != 3 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c") + } +} + func TestRedBlackTreeIteratorFirst(t *testing.T) { tree := NewWithIntComparator() tree.Put(3, "c") From e49a74aa9112c24526489ac3b075c4950c2204e3 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 27 Jun 2016 03:09:20 +0200 Subject: [PATCH 10/10] - test iterator end on reverse-iterable data structures - fix red-black tree iteration with explicit begin and end states - examples for iterators (with index and key) (with forward and reverse iteration) --- README.md | 66 +++++++++++++++++---- examples/{main => }/iteratorwithindex.go | 46 ++++++++++----- examples/iteratorwithkey.go | 75 ++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 24 deletions(-) rename examples/{main => }/iteratorwithindex.go (61%) create mode 100644 examples/iteratorwithkey.go diff --git a/README.md b/README.md index ad968b9..a491abb 100644 --- a/README.md +++ b/README.md @@ -649,8 +649,9 @@ All ordered containers have stateful iterators. Typically an iterator is obtaine #### IteratorWithIndex -A [iterator](#iterator) whose elements are referenced by an index. Typical usage: +An [iterator](#iterator) whose elements are referenced by an index. +Typical usage: ```go it := list.Iterator() for it.Next() { @@ -659,44 +660,89 @@ for it.Next() { } ``` +Other usages: +```go +if it.First() { + firstIndex, firstValue := it.Index(), it.Value() + ... +} +``` + +```go +for it.Begin(); it.Next(); { + ... +} +``` + #### IteratorWithKey -A [iterator](#iterator) whose elements are referenced by a key. Typical usage: +An [iterator](#iterator) whose elements are referenced by a key. +Typical usage: ```go -it := map.Iterator() +it := tree.Iterator() for it.Next() { key, value := it.Key(), it.Value() ... } ``` +Other usages: +```go +if it.First() { + firstKey, firstValue := it.Key(), it.Value() + ... +} +``` + +```go +for it.Begin(); it.Next(); { + ... +} +``` + #### ReverseIteratorWithIndex -A [iterator](#iterator) whose elements are referenced by an index. Typical usage: +An [iterator](#iterator) whose elements are referenced by an index. Provides all functions as [IteratorWithIndex](#iteratorwithindex), but can also be used for reverse iteration. +Typical usage of iteration in reverse: ```go it := list.Iterator() -for it.Next() { /* Move to end */ } -for it.Prev() { +for it.End(); it.Prev(); { index, value := it.Index(), it.Value() ... } ``` +Other usages: +```go +if it.Last() { + lastIndex, lastValue := it.Index(), it.Value() + ... +} +``` + #### ReverseIteratorWithKey -A [iterator](#iterator) whose elements are referenced by a key. Typical usage: +An [iterator](#iterator) whose elements are referenced by a key. Provides all functions as [IteratorWithKey](#iteratorwithkey), but can also be used for reverse iteration. +Typical usage of iteration in reverse: ```go -it := map.Iterator() -for it.Next() { /* Move to end */ } -for it.Prev() { +it := tree.Iterator() +for it.End(); it.Prev(); { key, value := it.Key(), it.Value() ... } ``` +Other usages: +```go +if it.Last() { + lastKey, lastValue := it.Key(), it.Value() + ... +} +``` + ### Enumerable Enumerable functions for ordered containers that implement [EnumerableWithIndex](#enumerablewithindex) or [EnumerableWithKey](#enumerablewithkey) interfaces. diff --git a/examples/main/iteratorwithindex.go b/examples/iteratorwithindex.go similarity index 61% rename from examples/main/iteratorwithindex.go rename to examples/iteratorwithindex.go index 6b715d4..8edfe30 100644 --- a/examples/main/iteratorwithindex.go +++ b/examples/iteratorwithindex.go @@ -24,7 +24,7 @@ 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 main +package examples import ( "fmt" @@ -32,24 +32,42 @@ import ( ) // IteratorWithIndexExample to demonstrate basic usage of IteratorWithIndex -//func IteratorWithIndexExample() { -func main() { - set := treeset.NewWithIntComparator() - set.Add(1, 2, 3) - - // Forward iteration +func IteratorWithIndexExample() { + set := treeset.NewWithStringComparator() + set.Add("a", "b", "c") it := set.Iterator() + + fmt.Print("\nForward iteration\n") for it.Next() { index, value := it.Index(), it.Value() - fmt.Println("Index: ", index, "Value: ", value) + fmt.Print("[", index, ":", value, "]") // [0:a][1:b][2:c] + } + + fmt.Print("\nForward iteration (again)\n") + for it.Begin(); it.Next(); { + index, value := it.Index(), it.Value() + fmt.Print("[", index, ":", value, "]") // [0:a][1:b][2:c] + } + + fmt.Print("\nBackward iteration\n") + for it.Prev() { + index, value := it.Index(), it.Value() + fmt.Print("[", index, ":", value, "]") // [2:c][1:b][0:a] } - // Backward iteration (reverse) - for it.Last(); ; { + fmt.Print("\nBackward iteration (again)\n") + for it.End(); it.Prev(); { index, value := it.Index(), it.Value() - fmt.Println("Index: ", index, "Value: ", value) - if !it.Prev() { - break - } + fmt.Print("[", index, ":", value, "]") // [2:c][1:b][0:a] + } + + if it.First() { + fmt.Print("\nFirst index: ", it.Index()) // First index: 0 + fmt.Print("\nFirst value: ", it.Value()) // First value: a + } + + if it.Last() { + fmt.Print("\nLast index: ", it.Index()) // Last index: 3 + fmt.Print("\nLast value: ", it.Value()) // Last value: c } } diff --git a/examples/iteratorwithkey.go b/examples/iteratorwithkey.go new file mode 100644 index 0000000..51716a2 --- /dev/null +++ b/examples/iteratorwithkey.go @@ -0,0 +1,75 @@ +/* +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 ( + "fmt" + "github.com/emirpasic/gods/maps/treemap" +) + +// IteratorWithKeyExample to demonstrate basic usage of IteratorWithKey +func IteratorWithKeyExample() { + m := treemap.NewWithIntComparator() + m.Put(1, "a") + m.Put(2, "b") + m.Put(3, "a") + it := m.Iterator() + + fmt.Print("\nForward iteration\n") + for it.Next() { + key, value := it.Key(), it.Value() + fmt.Print("[", key, ":", value, "]") // [0:a][1:b][2:c] + } + + fmt.Print("\nForward iteration (again)\n") + for it.Begin(); it.Next(); { + key, value := it.Key(), it.Value() + fmt.Print("[", key, ":", value, "]") // [0:a][1:b][2:c] + } + + fmt.Print("\nBackward iteration\n") + for it.Prev() { + key, value := it.Key(), it.Value() + fmt.Print("[", key, ":", value, "]") // [2:c][1:b][0:a] + } + + fmt.Print("\nBackward iteration (again)\n") + for it.End(); it.Prev(); { + key, value := it.Key(), it.Value() + fmt.Print("[", key, ":", value, "]") // [2:c][1:b][0:a] + } + + if it.First() { + fmt.Print("\nFirst key: ", it.Key()) // First key: 0 + fmt.Print("\nFirst value: ", it.Value()) // First value: a + } + + if it.Last() { + fmt.Print("\nLast key: ", it.Key()) // Last key: 3 + fmt.Print("\nLast value: ", it.Value()) // Last value: c + } +}