Some fixes. Also added the readme.

This commit is contained in:
Andrey Parhomenko 2023-08-27 15:33:44 +03:00
parent cd5aa6cec7
commit 34e21699a3
5 changed files with 104 additions and 34 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
exe exe
*.exe

8
readme Normal file
View file

@ -0,0 +1,8 @@
# godat
Golang custom data structures for specific purposes.
- Linked list: llx
- List: listx
- Sparse array: sparsex

View file

@ -7,18 +7,13 @@ import (
) )
func main() { func main() {
ll := llx.New[string]() ll := llx.New[string]("zero", "one", "two", "three", "four", "five")
ll.Append("zero")
ll.Append("one")
ll.Append("two")
ll.Append("three")
ll.Append("four")
ll.Push("minus one")
ll.Swap(1, 3) ll.Swap(0, 2)
for p := range ll.Chan() { for el := range ll.Chan() {
fmt.Println(p.K, p.V) fmt.Println(el)
} }
fmt.Println(ll.Slice())
} }

View file

@ -5,10 +5,6 @@ package llx
// linked list than in standard library since it uses // linked list than in standard library since it uses
// the new conception of generics. // the new conception of generics.
import (
"github.com/mojosa-software/godat/src/iterx"
)
// The type represents linked list data structure. // The type represents linked list data structure.
type LinkedList[V any] struct { type LinkedList[V any] struct {
// First empty element (not used to store values). // First empty element (not used to store values).
@ -27,12 +23,15 @@ type Element[V any] struct {
} }
// Returns new empty linked list storing the V type. // Returns new empty linked list storing the V type.
func New[V any]() *LinkedList[V] { func New[V any](values ...V) *LinkedList[V] {
return &LinkedList[V]{ ret := &LinkedList[V]{
&Element[V]{}, &Element[V]{},
nil, nil,
0, 0,
} }
ret.Append(values...)
return ret
} }
// Get length of the linked list. // Get length of the linked list.
@ -40,6 +39,10 @@ func (ll *LinkedList[V]) Length() int {
return ll.ln return ll.ln
} }
func (ll *LinkedList[V]) Len() int {
return ll.Length()
}
// Get the index-indexed element itself. // Get the index-indexed element itself.
func (ll *LinkedList[V]) GetEl(index int) (*Element[V], bool) { func (ll *LinkedList[V]) GetEl(index int) (*Element[V], bool) {
if ll.ln <= index { if ll.ln <= index {
@ -75,6 +78,41 @@ func (ll *LinkedList[V]) Set(i int, v V) (bool) {
return true return true
} }
// Insert the V value before the i-th element.
func (ll *LinkedList[V]) InsertBefore(v V, i int) {
if i == 0 {
ll.before = &Element[V]{
value: v,
next: ll.before.next,
}
return
}
el, ok := ll.GetEl(i-1)
if !ok {
panic("index out of range")
}
el.next = &Element[V]{
value: v,
next: el.next,
}
}
// Insert the V value after the i-th element.
func (ll *LinkedList[V]) InsertAfter(i int, v V) {
el, ok := ll.GetEl(i)
if !ok {
panic("index out of range")
}
el.next = &Element[V]{
value: v,
next: el.next,
}
}
// Swap element values indexed by i1 and i2.
// Panic on "index out of range".
func (ll *LinkedList[V]) Swap(i1, i2 int) { func (ll *LinkedList[V]) Swap(i1, i2 int) {
if i1 == i2 { if i1 == i2 {
return return
@ -93,16 +131,16 @@ func (ll *LinkedList[V]) Swap(i1, i2 int) {
} }
// Deletes the element by its index. // Deletes the element by its index.
func (ll *LinkedList[V]) Delete(i int) (bool) { func (ll *LinkedList[V]) Delete(i int) {
if ll.ln <= i { if ll.ln <= i && i < 0 {
return false panic("index out of range")
} }
if i == 0 { if i == 0 {
ll.before.next = ll.before.next =
ll.before.next.next ll.before.next.next
ll.ln-- ll.ln--
return true return
} }
el1, _ := ll.GetEl(i-1) el1, _ := ll.GetEl(i-1)
@ -114,11 +152,22 @@ func (ll *LinkedList[V]) Delete(i int) (bool) {
} }
ll.ln-- ll.ln--
return true }
// Alias to Delete method.
func (ll *LinkedList[V]) Del(i int) {
ll.Delete(i)
} }
// Push in the beginning of the list. // Push in the beginning of the list.
func (ll *LinkedList[V]) Push(v V) { func (ll *LinkedList[V]) Push(values ...V) {
for _, value := range values {
ll.push(value)
}
}
// Push in the beginning of the list.
func (ll *LinkedList[V]) push(v V) {
prevNext := ll.before.next prevNext := ll.before.next
nextNext := &Element[V]{ nextNext := &Element[V]{
next: prevNext, next: prevNext,
@ -133,7 +182,13 @@ func (ll *LinkedList[V]) Push(v V) {
} }
// Append to the end of the list. // Append to the end of the list.
func (ll *LinkedList[V]) Append(v V) { func (ll *LinkedList[V]) Append(values ...V) {
for _, value := range values {
ll.gappend(value)
}
}
func (ll *LinkedList[V]) gappend(v V) {
if ll.ln == 0 { if ll.ln == 0 {
ll.Push(v) ll.Push(v)
return return
@ -172,22 +227,34 @@ func (ll *LinkedList[V]) Last() *Element[V] {
return ll.last return ll.last
} }
// Returns a channel of Pair that contains index and the value. // Returns a channel with values ordered as in list.
func (ll *LinkedList[V]) Chan() iterx.PairChan[int, V] { func (ll *LinkedList[V]) Chan() chan V {
chn := make(iterx.PairChan[int, V]) chn := make(chan V)
go func(){ go func(){
i := -1
el := ll.before el := ll.before
for el.next != nil { for el.next != nil {
i++
el = el.next el = el.next
chn <- iterx.Pair[int, V]{ chn <- el.value
K: i,
V: el.value,
}
} }
close(chn) close(chn)
}() }()
return chn return chn
} }
// Returns slice of values in the list ordered as in the list.
func (ll *LinkedList[V]) Slice() []V {
buf := make([]V, ll.Length())
chn := ll.Chan()
i := 0
for v := range chn {
buf[i] = v
i++
}
return buf
}
func (ll *LinkedList[V]) Sort() {
}

View file

@ -20,11 +20,10 @@ type Sparse[K cons.Ordered, V any] struct {
// Returns new sparse array. // Returns new sparse array.
// If shouldSort == true then it will sort the array on // If shouldSort == true then it will sort the array on
// each change. // each change.
func New[K cons.Ordered, V any](shouldSort bool) *Sparse[K, V] { func New[K cons.Ordered, V any]() *Sparse[K, V] {
return &Sparse[K, V]{ return &Sparse[K, V]{
store: make(map[K] V), store: make(map[K] V),
keys: []K{}, keys: []K{},
shouldSort: shouldSort,
} }
} }