package lists import ( "vultras.su/core/gods" "sort" "fmt" ) // Linked list X . // The package implements better variation of // linked list than in standard library since it uses // the new conception of generics. // The type represents singly linked list data structure. type sLinkedList[V any] struct { // First empty element (not used to store values). // For fast pushing. before *sElement[V] // Points to the last for fast appending. last *sElement[V] // Length. ln int } // The type represents element of the linked list. type sElement[V any] struct { next *sElement[V] value V } func newSingly[V any](values ...V) *sLinkedList[V] { ret := &sLinkedList[V]{ before: &sElement[V]{}, last: nil, ln: 0, } ret.Add(values...) return ret } // Returns new empty linked list storing the V type. func NewSingly[V any](values ...V) List[V] { return newSingly[V](values...) } func (ll *sLinkedList[V]) Empty() bool { return ll.ln == 0 } func (ll *sLinkedList[V]) Size() int { return ll.ln } func (ll *sLinkedList[V]) Clear() { buf := newSingly[V]() *ll = *buf } func (ll *sLinkedList[V]) Len() int { return ll.ln } // Get the index-indexed element itself. func (ll *sLinkedList[V]) getEl(index int) *sElement[V] { if ll.ln <= index || index < 0 { panic(gods.IndexRangeErr) } p := ll.before for i := 0; i <= index; i++ { p = p.next } return p } // Get the value of index-indexed element. func (ll *sLinkedList[V]) Get(index int) V { return ll.getEl(index).value } // Set the new value in i-indexed element. func (ll *sLinkedList[V]) Set(i int, v V) { el := ll.getEl(i) el.value = v } // Insert the V value before the i-th element. func (ll *sLinkedList[V]) InsB(index int, values ...V) { if index == 0 { ll.Put(values...) return } el := ll.getEl(index - 1) for _, v := range values { el.next = &sElement[V]{ value: v, next: el.next, } el = el.next } ll.ln += len(values) } func (ll *sLinkedList[V]) InsA(index int, values ...V) { if index == ll.ln-1 { ll.Add(values...) return } el := ll.getEl(index) for _, v := range values { el.next = &sElement[V]{ value: v, next: el.next, } el = el.next } ll.ln += len(values) } func (ll *sLinkedList[V]) Swap(i1, i2 int) { if i1 == i2 { return } el1 := ll.getEl(i1) el2 := ll.getEl(i2) el1.value, el2.value = el2.value, el1.value } func (ll *sLinkedList[V]) Del(i int) { if i == 0 { ll.before.next = ll.before.next.next ll.ln-- return } el1 := ll.getEl(i - 1) if i == ll.ln-1 { el1.next = nil } else { el2 := ll.getEl(i + 1) el1.next = el2 } ll.ln-- } func (ll *sLinkedList[V]) Put(values ...V) { ln := len(values) for i := ln - 1; i >= 0; i-- { ll.Push(values[i]) } } func (ll *sLinkedList[V]) Pop() V { el := ll.before.next if el == nil { panic(gods.IndexRangeErr) } ll.before.next = el.next ll.ln-- return el.value } func (ll *sLinkedList[V]) Push(v V) { prevNext := ll.before.next nextNext := &sElement[V]{ next: prevNext, value: v, } ll.before.next = nextNext ll.ln++ if ll.ln == 1 { ll.last = ll.before.next } } // Append to the end of the list. func (ll *sLinkedList[V]) Add(values ...V) { for _, value := range values { ll.gappend(value) } } func (ll *sLinkedList[V]) gappend(v V) { if ll.ln == 0 { ll.Push(v) return } last := &sElement[V]{ next: nil, value: v, } lastBuf := ll.last lastBuf.next = last ll.last = last ll.ln++ } // Returns the first element of the linked list. func (ll *sLinkedList[V]) First() *sElement[V] { return ll.before.next } // Get elements value. func (ll *sElement[V]) Value() V { return ll.value } // Returns the next element. If the returned value == nil, // then it is the last element. func (ll *sElement[V]) Next() *sElement[V] { return ll.next } // Returns the last element. func (ll *sLinkedList[V]) Last() *sElement[V] { return ll.last } // Returns a channel with values ordered as in list. func (ll *sLinkedList[V]) Chan() chan V { chn := make(chan V) go func() { el := ll.before for el.next != nil { el = el.next chn <- el.value } close(chn) }() return chn } // Returns slice of values in the list ordered as in the list. func (ll *sLinkedList[V]) Values() []V { buf := make([]V, ll.Len()) i := 0 el := ll.before for el.next != nil { el = el.next buf[i] = el.value i++ } return buf } func (ll *sLinkedList[V]) String() string { return fmt.Sprintf("%v", ll.Values()) } func (ll *sLinkedList[V]) Sort(fn gods.LessFunc[V]) { sort.Sort(gods.CustomSort[V]{ CustomSorter: ll, LessFunc: fn, }) }