mirror of
https://github.com/emirpasic/gods
synced 2024-11-18 09:25:50 +00:00
commit
a35f503961
17
README.md
17
README.md
@ -126,7 +126,7 @@ func main() {
|
|||||||
|
|
||||||
####Lists
|
####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:
|
All lists implement the list interface with the following methods:
|
||||||
|
|
||||||
@ -134,10 +134,11 @@ All lists implement the list interface with the following methods:
|
|||||||
type Interface interface {
|
type Interface interface {
|
||||||
Get(index int) (interface{}, bool)
|
Get(index int) (interface{}, bool)
|
||||||
Remove(index int)
|
Remove(index int)
|
||||||
Add(elements ...interface{})
|
Add(values ...interface{})
|
||||||
Contains(elements ...interface{}) bool
|
Contains(values ...interface{}) bool
|
||||||
Sort(comparator utils.Comparator)
|
Sort(comparator utils.Comparator)
|
||||||
Swap(index1, index2 int)
|
Swap(index1, index2 int)
|
||||||
|
Insert(index int, values ...interface{})
|
||||||
|
|
||||||
containers.Interface
|
containers.Interface
|
||||||
// Empty() bool
|
// Empty() bool
|
||||||
@ -180,12 +181,14 @@ func main() {
|
|||||||
_ = list.Size() // 0
|
_ = list.Size() // 0
|
||||||
list.Add("a") // ["a"]
|
list.Add("a") // ["a"]
|
||||||
list.Clear() // []
|
list.Clear() // []
|
||||||
|
list.Insert(0, "b") // ["b"]
|
||||||
|
list.Insert(0, "a") // ["a","b"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#####SinglyLinkedList
|
#####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.
|
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.
|
||||||
|
|
||||||
@ -215,12 +218,14 @@ func main() {
|
|||||||
_ = list.Size() // 0
|
_ = list.Size() // 0
|
||||||
list.Add("a") // ["a"]
|
list.Add("a") // ["a"]
|
||||||
list.Clear() // []
|
list.Clear() // []
|
||||||
|
list.Insert(0, "b") // ["b"]
|
||||||
|
list.Insert(0, "a") // ["a","b"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#####DoublyLinkedList
|
#####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.
|
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.
|
||||||
|
|
||||||
@ -250,6 +255,8 @@ func main() {
|
|||||||
_ = list.Size() // 0
|
_ = list.Size() // 0
|
||||||
list.Add("a") // ["a"]
|
list.Add("a") // ["a"]
|
||||||
list.Clear() // []
|
list.Clear() // []
|
||||||
|
list.Insert(0, "b") // ["b"]
|
||||||
|
list.Insert(0, "a") // ["a","b"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -57,10 +57,10 @@ func New() *List {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Appends a value at the end of the list
|
// Appends a value at the end of the list
|
||||||
func (list *List) Add(elements ...interface{}) {
|
func (list *List) Add(values ...interface{}) {
|
||||||
list.growBy(len(elements))
|
list.growBy(len(values))
|
||||||
for _, element := range elements {
|
for _, value := range values {
|
||||||
list.elements[list.size] = element
|
list.elements[list.size] = value
|
||||||
list.size += 1
|
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.
|
// All elements have to be present in the set for the method to return true.
|
||||||
// Performance time complexity of n^2.
|
// 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.
|
// 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
|
found := false
|
||||||
for _, element := range list.elements {
|
for _, element := range list.elements {
|
||||||
if element == searchElement {
|
if element == searchValue {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -142,13 +142,39 @@ func (list *List) Sort(comparator utils.Comparator) {
|
|||||||
utils.Sort(list.elements[:list.size], 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) {
|
func (list *List) Swap(i, j int) {
|
||||||
if list.withinRange(i) && list.withinRange(j) {
|
if list.withinRange(i) && list.withinRange(j) {
|
||||||
list.elements[i], list.elements[j] = list.elements[j], list.elements[i]
|
list.elements[i], list.elements[j] = list.elements[j], list.elements[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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...)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := len(values)
|
||||||
|
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, value := range values {
|
||||||
|
list.elements[index+i] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (list *List) String() string {
|
func (list *List) String() string {
|
||||||
str := "ArrayList\n"
|
str := "ArrayList\n"
|
||||||
values := []string{}
|
values := []string{}
|
||||||
@ -161,7 +187,7 @@ func (list *List) String() string {
|
|||||||
|
|
||||||
// Check that the index is withing bounds of the list
|
// Check that the index is withing bounds of the list
|
||||||
func (list *List) withinRange(index int) bool {
|
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) {
|
func (list *List) resize(cap int) {
|
||||||
|
@ -27,6 +27,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
package arraylist
|
package arraylist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/emirpasic/gods/utils"
|
"github.com/emirpasic/gods/utils"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -120,6 +121,19 @@ func TestArrayList(t *testing.T) {
|
|||||||
t.Errorf("Got %v expected %v", actualValue, true)
|
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) {
|
func BenchmarkArrayList(b *testing.B) {
|
||||||
|
@ -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 {
|
func (list *List) String() string {
|
||||||
str := "DoublyLinkedList\n"
|
str := "DoublyLinkedList\n"
|
||||||
values := []string{}
|
values := []string{}
|
||||||
@ -256,5 +310,5 @@ func (list *List) String() string {
|
|||||||
|
|
||||||
// Check that the index is withing bounds of the list
|
// Check that the index is withing bounds of the list
|
||||||
func (list *List) withinRange(index int) bool {
|
func (list *List) withinRange(index int) bool {
|
||||||
return index >= 0 && index < list.size && list.size != 0
|
return index >= 0 && index < list.size
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
package doublylinkedlist
|
package doublylinkedlist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/emirpasic/gods/utils"
|
"github.com/emirpasic/gods/utils"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -122,6 +123,19 @@ func TestDoublyLinkedList(t *testing.T) {
|
|||||||
t.Errorf("Got %v expected %v", actualValue, true)
|
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) {
|
func BenchmarkDoublyLinkedList(b *testing.B) {
|
||||||
|
@ -26,10 +26,11 @@ import (
|
|||||||
type Interface interface {
|
type Interface interface {
|
||||||
Get(index int) (interface{}, bool)
|
Get(index int) (interface{}, bool)
|
||||||
Remove(index int)
|
Remove(index int)
|
||||||
Add(elements ...interface{})
|
Add(values ...interface{})
|
||||||
Contains(elements ...interface{}) bool
|
Contains(values ...interface{}) bool
|
||||||
Sort(comparator utils.Comparator)
|
Sort(comparator utils.Comparator)
|
||||||
Swap(index1, index2 int)
|
Swap(index1, index2 int)
|
||||||
|
Insert(index int, values ...interface{})
|
||||||
|
|
||||||
containers.Interface
|
containers.Interface
|
||||||
// Empty() bool
|
// Empty() bool
|
||||||
|
@ -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 {
|
func (list *List) String() string {
|
||||||
str := "SinglyLinkedList\n"
|
str := "SinglyLinkedList\n"
|
||||||
values := []string{}
|
values := []string{}
|
||||||
@ -235,5 +280,5 @@ func (list *List) String() string {
|
|||||||
|
|
||||||
// Check that the index is withing bounds of the list
|
// Check that the index is withing bounds of the list
|
||||||
func (list *List) withinRange(index int) bool {
|
func (list *List) withinRange(index int) bool {
|
||||||
return index >= 0 && index < list.size && list.size != 0
|
return index >= 0 && index < list.size
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
package singlylinkedlist
|
package singlylinkedlist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/emirpasic/gods/utils"
|
"github.com/emirpasic/gods/utils"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -122,6 +123,19 @@ func TestSinglyLinkedList(t *testing.T) {
|
|||||||
t.Errorf("Got %v expected %v", actualValue, true)
|
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) {
|
func BenchmarkSinglyLinkedList(b *testing.B) {
|
||||||
|
Loading…
Reference in New Issue
Block a user