From dd0fbaa365a36d9072dcc883b6f1775e26925a98 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Tue, 21 Jun 2016 03:29:29 +0200 Subject: [PATCH] - 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) {