From c7abdd28b35b670f506d5746cf14f871d98abd17 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Tue, 21 Jun 2016 02:22:20 +0200 Subject: [PATCH 1/4] - add insert for list and arraylist --- README.md | 3 +++ lists/arraylist/arraylist.go | 28 +++++++++++++++++++++++++++- lists/arraylist/arraylist_test.go | 14 ++++++++++++++ lists/lists.go | 1 + 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 443c37d..4095445 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,7 @@ type Interface interface { Contains(elements ...interface{}) bool Sort(comparator utils.Comparator) Swap(index1, index2 int) + Insert(index int, elements ...interface{}) containers.Interface // Empty() bool @@ -180,6 +181,8 @@ func main() { _ = list.Size() // 0 list.Add("a") // ["a"] list.Clear() // [] + list.Insert(0, "b") // ["b"] + list.Insert(0, "a") // ["a","b"] } ``` diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go index f98b5e5..c3b9f0f 100644 --- a/lists/arraylist/arraylist.go +++ b/lists/arraylist/arraylist.go @@ -149,6 +149,32 @@ func (list *List) Swap(i, j int) { } } +// Inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right. +// Does not do anything if position is negative or bigger than list's size +// Note: position equal to list's size is valid, i.e. append. +func (list *List) Insert(index int, elements ...interface{}) { + + if !list.withinRange(index) { + // Append + if index == list.size { + list.Add(elements...) + } + return + } + + l := len(elements) + list.growBy(l) + list.size += l + // Shift old to right + for i := list.size - 1; i >= index+l; i-- { + list.elements[i] = list.elements[i-l] + } + // Insert new + for i, element := range elements { + list.elements[index+i] = element + } +} + func (list *List) String() string { str := "ArrayList\n" values := []string{} @@ -161,7 +187,7 @@ func (list *List) String() string { // Check that the index is withing bounds of the list func (list *List) withinRange(index int) bool { - return index >= 0 && index < list.size && list.size != 0 + return index >= 0 && index < list.size } func (list *List) resize(cap int) { diff --git a/lists/arraylist/arraylist_test.go b/lists/arraylist/arraylist_test.go index 4eb239f..ab07f67 100644 --- a/lists/arraylist/arraylist_test.go +++ b/lists/arraylist/arraylist_test.go @@ -27,6 +27,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package arraylist import ( + "fmt" "github.com/emirpasic/gods/utils" "testing" ) @@ -120,6 +121,19 @@ func TestArrayList(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, true) } + list.Insert(0, "h") + list.Insert(0, "e") + list.Insert(1, "f") + list.Insert(2, "g") + list.Insert(4, "i") + list.Insert(0, "a", "b") + list.Insert(list.Size(), "j", "k") + list.Insert(2, "c", "d") + + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s%s%s%s%s", list.Values()...), "abcdefghijk"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } func BenchmarkArrayList(b *testing.B) { diff --git a/lists/lists.go b/lists/lists.go index 7e03285..7de3cb0 100644 --- a/lists/lists.go +++ b/lists/lists.go @@ -30,6 +30,7 @@ type Interface interface { Contains(elements ...interface{}) bool Sort(comparator utils.Comparator) Swap(index1, index2 int) + Insert(index int, elements ...interface{}) containers.Interface // Empty() bool From 875dab737f96fda02977a735413d701c4d906c59 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Tue, 21 Jun 2016 03:15:02 +0200 Subject: [PATCH 2/4] - add insert for singlylinkedlist --- README.md | 2 + lists/singlylinkedlist/singlylinkedlist.go | 47 ++++++++++++++++++- .../singlylinkedlist/singlylinkedlist_test.go | 14 ++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4095445..66dda49 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,8 @@ func main() { _ = list.Size() // 0 list.Add("a") // ["a"] list.Clear() // [] + list.Insert(0, "b") // ["b"] + list.Insert(0, "a") // ["a","b"] } ``` diff --git a/lists/singlylinkedlist/singlylinkedlist.go b/lists/singlylinkedlist/singlylinkedlist.go index a9b4d63..e4730ae 100644 --- a/lists/singlylinkedlist/singlylinkedlist.go +++ b/lists/singlylinkedlist/singlylinkedlist.go @@ -223,6 +223,51 @@ func (list *List) Swap(i, j int) { } } +// Inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right. +// Does not do anything if position is negative or bigger than list's size +// Note: position equal to list's size is valid, i.e. append. +func (list *List) Insert(index int, values ...interface{}) { + + if !list.withinRange(index) { + // Append + if index == list.size { + list.Add(values...) + } + fmt.Println(list.Values()) + return + } + + list.size += len(values) + + var beforeElement *element + foundElement := list.first + for e := 0; e != index; e, foundElement = e+1, foundElement.next { + beforeElement = foundElement + } + + if foundElement == list.first { + oldNextElement := list.first + for i, value := range values { + newElement := &element{value: value} + if i == 0 { + list.first = newElement + } else { + beforeElement.next = newElement + } + beforeElement = newElement + } + beforeElement.next = oldNextElement + } else { + oldNextElement := beforeElement.next + for _, value := range values { + newElement := &element{value: value} + beforeElement.next = newElement + beforeElement = newElement + } + beforeElement.next = oldNextElement + } +} + func (list *List) String() string { str := "SinglyLinkedList\n" values := []string{} @@ -235,5 +280,5 @@ func (list *List) String() string { // Check that the index is withing bounds of the list func (list *List) withinRange(index int) bool { - return index >= 0 && index < list.size && list.size != 0 + return index >= 0 && index < list.size } diff --git a/lists/singlylinkedlist/singlylinkedlist_test.go b/lists/singlylinkedlist/singlylinkedlist_test.go index 4956507..df08466 100644 --- a/lists/singlylinkedlist/singlylinkedlist_test.go +++ b/lists/singlylinkedlist/singlylinkedlist_test.go @@ -27,6 +27,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package singlylinkedlist import ( + "fmt" "github.com/emirpasic/gods/utils" "testing" ) @@ -122,6 +123,19 @@ func TestSinglyLinkedList(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, true) } + list.Insert(0, "h") + list.Insert(0, "e") + list.Insert(1, "f") + list.Insert(2, "g") + list.Insert(4, "i") + list.Insert(0, "a", "b") + list.Insert(list.Size(), "j", "k") + list.Insert(2, "c", "d") + + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s%s%s%s%s", list.Values()...), "abcdefghijk"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } func BenchmarkSinglyLinkedList(b *testing.B) { From dd0fbaa365a36d9072dcc883b6f1775e26925a98 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Tue, 21 Jun 2016 03:29:29 +0200 Subject: [PATCH 3/4] - add insert for doublylinkedlist --- README.md | 2 + lists/doublylinkedlist/doublylinkedlist.go | 54 +++++++++++++++++++ .../doublylinkedlist/doublylinkedlist_test.go | 14 +++++ 3 files changed, 70 insertions(+) diff --git a/README.md b/README.md index 66dda49..6897e39 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,8 @@ func main() { _ = list.Size() // 0 list.Add("a") // ["a"] list.Clear() // [] + list.Insert(0, "b") // ["b"] + list.Insert(0, "a") // ["a","b"] } ``` diff --git a/lists/doublylinkedlist/doublylinkedlist.go b/lists/doublylinkedlist/doublylinkedlist.go index ed40eeb..b948d8b 100644 --- a/lists/doublylinkedlist/doublylinkedlist.go +++ b/lists/doublylinkedlist/doublylinkedlist.go @@ -244,6 +244,60 @@ func (list *List) Swap(i, j int) { } } +// Inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right. +// Does not do anything if position is negative or bigger than list's size +// Note: position equal to list's size is valid, i.e. append. +func (list *List) Insert(index int, values ...interface{}) { + + if !list.withinRange(index) { + // Append + if index == list.size { + list.Add(values...) + } + fmt.Println(list.Values()) + return + } + + list.size += len(values) + + var beforeElement *element + var foundElement *element + // determine traversal direction, last to first or first to last + if list.size-index < index { + foundElement = list.last + for e := list.size - 1; e != index; e, foundElement = e-1, foundElement.prev { + beforeElement = foundElement.prev + } + } else { + foundElement = list.first + for e := 0; e != index; e, foundElement = e+1, foundElement.next { + beforeElement = foundElement + } + } + + if foundElement == list.first { + oldNextElement := list.first + for i, value := range values { + newElement := &element{value: value} + if i == 0 { + list.first = newElement + } else { + beforeElement.next = newElement + } + beforeElement = newElement + } + beforeElement.next = oldNextElement + } else { + oldNextElement := beforeElement.next + for _, value := range values { + newElement := &element{value: value} + beforeElement.next = newElement + beforeElement = newElement + } + beforeElement.next = oldNextElement + } +} + func (list *List) String() string { str := "DoublyLinkedList\n" values := []string{} diff --git a/lists/doublylinkedlist/doublylinkedlist_test.go b/lists/doublylinkedlist/doublylinkedlist_test.go index 0c78c7b..528b00f 100644 --- a/lists/doublylinkedlist/doublylinkedlist_test.go +++ b/lists/doublylinkedlist/doublylinkedlist_test.go @@ -27,6 +27,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package doublylinkedlist import ( + "fmt" "github.com/emirpasic/gods/utils" "testing" ) @@ -122,6 +123,19 @@ func TestDoublyLinkedList(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, true) } + list.Insert(0, "h") + list.Insert(0, "e") + list.Insert(1, "f") + list.Insert(2, "g") + list.Insert(4, "i") + list.Insert(0, "a", "b") + list.Insert(list.Size(), "j", "k") + list.Insert(2, "c", "d") + + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s%s%s%s%s", list.Values()...), "abcdefghijk"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } func BenchmarkDoublyLinkedList(b *testing.B) { From 56b8a594888a2a02f77b46333242e56a09aedc2b Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Tue, 21 Jun 2016 03:39:47 +0200 Subject: [PATCH 4/4] - update all lists to use "value" terminology for coherence, e.g. Add(values...) rather than Add(elements...) --- README.md | 12 +++++----- lists/arraylist/arraylist.go | 26 +++++++++++----------- lists/doublylinkedlist/doublylinkedlist.go | 2 +- lists/lists.go | 6 ++--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 6897e39..deed77b 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ func main() { ####Lists -A list is a data structure that can store elements and may have repeated values. There is no ordering in a list. The user can access and remove an element by the index position. +A list is a data structure that can store values and may have repeated values. There is no ordering in a list. The user can access and remove a value by the index position. All lists implement the list interface with the following methods: @@ -134,11 +134,11 @@ All lists implement the list interface with the following methods: type Interface interface { Get(index int) (interface{}, bool) Remove(index int) - Add(elements ...interface{}) - Contains(elements ...interface{}) bool + Add(values ...interface{}) + Contains(values ...interface{}) bool Sort(comparator utils.Comparator) Swap(index1, index2 int) - Insert(index int, elements ...interface{}) + Insert(index int, values ...interface{}) containers.Interface // Empty() bool @@ -188,7 +188,7 @@ func main() { #####SinglyLinkedList -This structure implements the _List_ interface and is a linked data structure where each element points to the next in the list. +This structure implements the _List_ interface and is a linked data structure where each value points to the next in the list. Direct access method _Get(index)_ and _Remove()_ are of linear performance. _Append_ and _Prepend_ are of constant time performance. Checking with _Contains()_ is of quadratic complexity. @@ -225,7 +225,7 @@ func main() { #####DoublyLinkedList -This structure implements the _List_ interface and is a linked data structure where each element points to the next and previous element in the list. +This structure implements the _List_ interface and is a linked data structure where each value points to the next and previous element in the list. Direct access method _Get(index)_ and _Remove()_ are of linear performance. _Append_ and _Prepend_ are of constant time performance. Checking with _Contains()_ is of quadratic complexity. diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go index c3b9f0f..278f153 100644 --- a/lists/arraylist/arraylist.go +++ b/lists/arraylist/arraylist.go @@ -57,10 +57,10 @@ func New() *List { } // Appends a value at the end of the list -func (list *List) Add(elements ...interface{}) { - list.growBy(len(elements)) - for _, element := range elements { - list.elements[list.size] = element +func (list *List) Add(values ...interface{}) { + list.growBy(len(values)) + for _, value := range values { + list.elements[list.size] = value list.size += 1 } } @@ -94,12 +94,12 @@ func (list *List) Remove(index int) { // All elements have to be present in the set for the method to return true. // Performance time complexity of n^2. // Returns true if no arguments are passed at all, i.e. set is always super-set of empty set. -func (list *List) Contains(elements ...interface{}) bool { +func (list *List) Contains(values ...interface{}) bool { - for _, searchElement := range elements { + for _, searchValue := range values { found := false for _, element := range list.elements { - if element == searchElement { + if element == searchValue { found = true break } @@ -142,7 +142,7 @@ func (list *List) Sort(comparator utils.Comparator) { utils.Sort(list.elements[:list.size], comparator) } -// Swaps values of two elements at the given indices. +// Swaps the two values at the specified positions. func (list *List) Swap(i, j int) { if list.withinRange(i) && list.withinRange(j) { list.elements[i], list.elements[j] = list.elements[j], list.elements[i] @@ -152,17 +152,17 @@ func (list *List) Swap(i, j int) { // Inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right. // Does not do anything if position is negative or bigger than list's size // Note: position equal to list's size is valid, i.e. append. -func (list *List) Insert(index int, elements ...interface{}) { +func (list *List) Insert(index int, values ...interface{}) { if !list.withinRange(index) { // Append if index == list.size { - list.Add(elements...) + list.Add(values...) } return } - l := len(elements) + l := len(values) list.growBy(l) list.size += l // Shift old to right @@ -170,8 +170,8 @@ func (list *List) Insert(index int, elements ...interface{}) { list.elements[i] = list.elements[i-l] } // Insert new - for i, element := range elements { - list.elements[index+i] = element + for i, value := range values { + list.elements[index+i] = value } } diff --git a/lists/doublylinkedlist/doublylinkedlist.go b/lists/doublylinkedlist/doublylinkedlist.go index b948d8b..b679797 100644 --- a/lists/doublylinkedlist/doublylinkedlist.go +++ b/lists/doublylinkedlist/doublylinkedlist.go @@ -310,5 +310,5 @@ func (list *List) String() string { // Check that the index is withing bounds of the list func (list *List) withinRange(index int) bool { - return index >= 0 && index < list.size && list.size != 0 + return index >= 0 && index < list.size } diff --git a/lists/lists.go b/lists/lists.go index 7de3cb0..5a83a4c 100644 --- a/lists/lists.go +++ b/lists/lists.go @@ -26,11 +26,11 @@ import ( type Interface interface { Get(index int) (interface{}, bool) Remove(index int) - Add(elements ...interface{}) - Contains(elements ...interface{}) bool + Add(values ...interface{}) + Contains(values ...interface{}) bool Sort(comparator utils.Comparator) Swap(index1, index2 int) - Insert(index int, elements ...interface{}) + Insert(index int, values ...interface{}) containers.Interface // Empty() bool