Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lists/singlylinkedlist/serialization.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ var _ containers.JSONSerializer = (*List[int])(nil)
var _ containers.JSONDeserializer = (*List[int])(nil)

// ToJSON outputs the JSON representation of list's elements.
func (list *List[T]) ToJSON() ([]byte, error) {
func (list *SimpleList[T]) ToJSON() ([]byte, error) {
return json.Marshal(list.Values())
}

// FromJSON populates list's elements from the input JSON representation.
func (list *List[T]) FromJSON(data []byte) error {
func (list *SimpleList[T]) FromJSON(data []byte) error {
var elements []T
err := json.Unmarshal(data, &elements)
if err == nil {
Expand All @@ -31,11 +31,11 @@ func (list *List[T]) FromJSON(data []byte) error {
}

// UnmarshalJSON @implements json.Unmarshaler
func (list *List[T]) UnmarshalJSON(bytes []byte) error {
func (list *SimpleList[T]) UnmarshalJSON(bytes []byte) error {
return list.FromJSON(bytes)
}

// MarshalJSON @implements json.Marshaler
func (list *List[T]) MarshalJSON() ([]byte, error) {
func (list *SimpleList[T]) MarshalJSON() ([]byte, error) {
return list.ToJSON()
}
156 changes: 86 additions & 70 deletions lists/singlylinkedlist/singlylinkedlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ var _ lists.List[int] = (*List[int])(nil)

// List holds the elements, where each element points to the next element
type List[T comparable] struct {
SimpleList[T]
}

// SimpleList is like [List] but it doesn't have any method that require T to be comparable. That lets
// SimpleList be used in places where [List] can't be used and it allows types like [linkedliststack.Stack] which
// don't have any method that require comparable elements to not require their generic type to be comparable.
type SimpleList[T any] struct {
first *element[T]
last *element[T]
size int
}

type element[T comparable] struct {
type element[T any] struct {
value T
next *element[T]
}
Expand All @@ -42,8 +49,16 @@ func New[T comparable](values ...T) *List[T] {
return list
}

func NewSimpleList[T any](values ...T) *SimpleList[T] {
list := &SimpleList[T]{}
if len(values) > 0 {
list.Add(values...)
}
return list
}

// Add appends a value (one or more) at the end of the list (same as Append())
func (list *List[T]) Add(values ...T) {
func (list *SimpleList[T]) Add(values ...T) {
for _, value := range values {
newElement := &element[T]{value: value}
if list.size == 0 {
Expand All @@ -58,12 +73,12 @@ func (list *List[T]) Add(values ...T) {
}

// Append appends a value (one or more) at the end of the list (same as Add())
func (list *List[T]) Append(values ...T) {
func (list *SimpleList[T]) Append(values ...T) {
list.Add(values...)
}

// Prepend prepends a values (or more)
func (list *List[T]) Prepend(values ...T) {
func (list *SimpleList[T]) Prepend(values ...T) {
// in reverse to keep passed order i.e. ["c","d"] -> Prepend(["a","b"]) -> ["a","b","c",d"]
for v := len(values) - 1; v >= 0; v-- {
newElement := &element[T]{value: values[v], next: list.first}
Expand All @@ -77,7 +92,7 @@ func (list *List[T]) Prepend(values ...T) {

// Get returns the element at index.
// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false.
func (list *List[T]) Get(index int) (T, bool) {
func (list *SimpleList[T]) Get(index int) (T, bool) {

if !list.withinRange(index) {
var t T
Expand All @@ -92,7 +107,7 @@ func (list *List[T]) Get(index int) (T, bool) {
}

// Remove removes the element at the given index from the list.
func (list *List[T]) Remove(index int) {
func (list *SimpleList[T]) Remove(index int) {

if !list.withinRange(index) {
return
Expand Down Expand Up @@ -124,90 +139,35 @@ func (list *List[T]) Remove(index int) {
list.size--
}

// Contains checks if values (one or more) are present in the set.
// All values 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[T]) Contains(values ...T) bool {

if len(values) == 0 {
return true
}
if list.size == 0 {
return false
}
for _, value := range values {
found := false
for element := list.first; element != nil; element = element.next {
if element.value == value {
found = true
break
}
}
if !found {
return false
}
}
return true
}

// Values returns all elements in the list.
func (list *List[T]) Values() []T {
func (list *SimpleList[T]) Values() []T {
values := make([]T, list.size, list.size)
for e, element := 0, list.first; element != nil; e, element = e+1, element.next {
values[e] = element.value
}
return values
}

// IndexOf returns index of provided element
func (list *List[T]) IndexOf(value T) int {
if list.size == 0 {
return -1
}
for index, element := range list.Values() {
if element == value {
return index
}
}
return -1
}

// Empty returns true if list does not contain any elements.
func (list *List[T]) Empty() bool {
func (list *SimpleList[T]) Empty() bool {
return list.size == 0
}

// Size returns number of elements within the list.
func (list *List[T]) Size() int {
func (list *SimpleList[T]) Size() int {
return list.size
}

// Clear removes all elements from the list.
func (list *List[T]) Clear() {
func (list *SimpleList[T]) Clear() {
list.size = 0
list.first = nil
list.last = nil
}

// Sort sort values (in-place) using.
func (list *List[T]) Sort(comparator utils.Comparator[T]) {

if list.size < 2 {
return
}

values := list.Values()
slices.SortFunc(values, comparator)

list.Clear()

list.Add(values...)

}

// Swap swaps values of two elements at the given indices.
func (list *List[T]) Swap(i, j int) {
func (list *SimpleList[T]) Swap(i, j int) {
if list.withinRange(i) && list.withinRange(j) && i != j {
var element1, element2 *element[T]
for e, currentElement := 0, list.first; element1 == nil || element2 == nil; e, currentElement = e+1, currentElement.next {
Expand All @@ -225,7 +185,7 @@ func (list *List[T]) Swap(i, j int) {
// Insert 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[T]) Insert(index int, values ...T) {
func (list *SimpleList[T]) Insert(index int, values ...T) {

if !list.withinRange(index) {
// Append
Expand Down Expand Up @@ -269,7 +229,7 @@ func (list *List[T]) Insert(index int, values ...T) {
// Set value at specified index
// 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[T]) Set(index int, value T) {
func (list *SimpleList[T]) Set(index int, value T) {

if !list.withinRange(index) {
// Append
Expand All @@ -287,7 +247,7 @@ func (list *List[T]) Set(index int, value T) {
}

// String returns a string representation of container
func (list *List[T]) String() string {
func (list *SimpleList[T]) String() string {
str := "SinglyLinkedList\n"
values := []string{}
for element := list.first; element != nil; element = element.next {
Expand All @@ -298,6 +258,62 @@ func (list *List[T]) String() string {
}

// Check that the index is within bounds of the list
func (list *List[T]) withinRange(index int) bool {
func (list *SimpleList[T]) withinRange(index int) bool {
return index >= 0 && index < list.size
}

// Contains checks if values (one or more) are present in the set.
// All values 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[T]) Contains(values ...T) bool {

if len(values) == 0 {
return true
}
if list.size == 0 {
return false
}
for _, value := range values {
found := false
for element := list.first; element != nil; element = element.next {
if element.value == value {
found = true
break
}
}
if !found {
return false
}
}
return true
}

// Sort sort values (in-place) using.
func (list *List[T]) Sort(comparator utils.Comparator[T]) {

if list.size < 2 {
return
}

values := list.Values()
slices.SortFunc(values, comparator)

list.Clear()

list.Add(values...)

}

// IndexOf returns index of provided element
func (list *List[T]) IndexOf(value T) int {
if list.size == 0 {
return -1
}
for index, element := range list.Values() {
if element == value {
return index
}
}
return -1
}
2 changes: 1 addition & 1 deletion stacks/linkedliststack/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.IteratorWithIndex[int] = (*Iterator[int])(nil)

// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator[T comparable] struct {
type Iterator[T any] struct {
stack *Stack[T]
index int
}
Expand Down
8 changes: 4 additions & 4 deletions stacks/linkedliststack/linkedliststack.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import (
var _ stacks.Stack[int] = (*Stack[int])(nil)

// Stack holds elements in a singly-linked-list
type Stack[T comparable] struct {
list *singlylinkedlist.List[T]
type Stack[T any] struct {
list *singlylinkedlist.SimpleList[T]
}

// New nnstantiates a new empty stack
func New[T comparable]() *Stack[T] {
return &Stack[T]{list: singlylinkedlist.New[T]()}
func New[T any]() *Stack[T] {
return &Stack[T]{list: singlylinkedlist.NewSimpleList[T]()}
}

// Push adds a value onto the top of the stack
Expand Down