diff --git a/.gitignore b/.gitignore index 86daf54..de315f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ exe +*.exe diff --git a/readme b/readme new file mode 100644 index 0000000..178ce68 --- /dev/null +++ b/readme @@ -0,0 +1,8 @@ +# godat + +Golang custom data structures for specific purposes. + +- Linked list: llx +- List: listx +- Sparse array: sparsex + diff --git a/src/cmd/ll/main.go b/src/cmd/ll/main.go index 7d8c709..ebaa7f8 100644 --- a/src/cmd/ll/main.go +++ b/src/cmd/ll/main.go @@ -7,18 +7,13 @@ import ( ) func main() { - ll := llx.New[string]() - ll.Append("zero") - ll.Append("one") - ll.Append("two") - ll.Append("three") - ll.Append("four") - ll.Push("minus one") + ll := llx.New[string]("zero", "one", "two", "three", "four", "five") - ll.Swap(1, 3) + ll.Swap(0, 2) - for p := range ll.Chan() { - fmt.Println(p.K, p.V) + for el := range ll.Chan() { + fmt.Println(el) } + fmt.Println(ll.Slice()) } diff --git a/src/llx/main.go b/src/llx/main.go index c6b0c87..1a6bbf8 100644 --- a/src/llx/main.go +++ b/src/llx/main.go @@ -5,10 +5,6 @@ package llx // linked list than in standard library since it uses // the new conception of generics. -import ( - "github.com/mojosa-software/godat/src/iterx" -) - // The type represents linked list data structure. type LinkedList[V any] struct { // 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. -func New[V any]() *LinkedList[V] { - return &LinkedList[V]{ +func New[V any](values ...V) *LinkedList[V] { + ret := &LinkedList[V]{ &Element[V]{}, nil, 0, } + + ret.Append(values...) + return ret } // Get length of the linked list. @@ -40,6 +39,10 @@ func (ll *LinkedList[V]) Length() int { return ll.ln } +func (ll *LinkedList[V]) Len() int { + return ll.Length() +} + // Get the index-indexed element itself. func (ll *LinkedList[V]) GetEl(index int) (*Element[V], bool) { if ll.ln <= index { @@ -75,6 +78,41 @@ func (ll *LinkedList[V]) Set(i int, v V) (bool) { 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) { if i1 == i2 { return @@ -93,16 +131,16 @@ func (ll *LinkedList[V]) Swap(i1, i2 int) { } // Deletes the element by its index. -func (ll *LinkedList[V]) Delete(i int) (bool) { - if ll.ln <= i { - return false +func (ll *LinkedList[V]) Delete(i int) { + if ll.ln <= i && i < 0 { + panic("index out of range") } if i == 0 { ll.before.next = ll.before.next.next ll.ln-- - return true + return } el1, _ := ll.GetEl(i-1) @@ -114,11 +152,22 @@ func (ll *LinkedList[V]) Delete(i int) (bool) { } 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. -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 nextNext := &Element[V]{ next: prevNext, @@ -133,7 +182,13 @@ func (ll *LinkedList[V]) Push(v V) { } // 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 { ll.Push(v) return @@ -172,22 +227,34 @@ func (ll *LinkedList[V]) Last() *Element[V] { return ll.last } -// Returns a channel of Pair that contains index and the value. -func (ll *LinkedList[V]) Chan() iterx.PairChan[int, V] { - chn := make(iterx.PairChan[int, V]) +// Returns a channel with values ordered as in list. +func (ll *LinkedList[V]) Chan() chan V { + chn := make(chan V) go func(){ - i := -1 el := ll.before for el.next != nil { - i++ el = el.next - chn <- iterx.Pair[int, V]{ - K: i, - V: el.value, - } + chn <- el.value } close(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() { +} + diff --git a/src/sparsex/main.go b/src/sparsex/main.go index 2d392bc..538a914 100644 --- a/src/sparsex/main.go +++ b/src/sparsex/main.go @@ -20,11 +20,10 @@ type Sparse[K cons.Ordered, V any] struct { // Returns new sparse array. // If shouldSort == true then it will sort the array on // 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]{ store: make(map[K] V), keys: []K{}, - shouldSort: shouldSort, } }