126 lines
2.3 KiB
Go
126 lines
2.3 KiB
Go
|
package collection
|
|||
|
|
|||
|
import (
|
|||
|
. "gitea.zaclys.com/bvaudour/gob/option"
|
|||
|
)
|
|||
|
|
|||
|
// List représente une collection d’élément qui peut être modifiée (ajout/suppression) par chaque bout.
|
|||
|
// Elle peut donc se comporter à la fois comme une pile et une file.
|
|||
|
type List[T any] struct {
|
|||
|
first *dualChain[T]
|
|||
|
last *dualChain[T]
|
|||
|
size uint
|
|||
|
}
|
|||
|
|
|||
|
// Len retourne le nombre d’éléments de la liste.
|
|||
|
func (l *List[T]) Len() uint {
|
|||
|
return l.size
|
|||
|
}
|
|||
|
|
|||
|
func (l *List[T]) push_front(e T) {
|
|||
|
var (
|
|||
|
c = newDual(e)
|
|||
|
oldFirst Option[*dualChain[T]]
|
|||
|
)
|
|||
|
|
|||
|
if l.size == 0 {
|
|||
|
l.last = c
|
|||
|
} else {
|
|||
|
oldFirst = Some(l.first)
|
|||
|
}
|
|||
|
|
|||
|
link(Some(c), oldFirst)
|
|||
|
l.first = c
|
|||
|
l.size++
|
|||
|
}
|
|||
|
|
|||
|
func (l *List[T]) push_back(e T) {
|
|||
|
var (
|
|||
|
c = newDual(e)
|
|||
|
oldLast Option[*dualChain[T]]
|
|||
|
)
|
|||
|
|
|||
|
if l.size == 0 {
|
|||
|
l.first = c
|
|||
|
} else {
|
|||
|
oldLast = Some(l.last)
|
|||
|
}
|
|||
|
link(oldLast, Some(c))
|
|||
|
|
|||
|
l.last = c
|
|||
|
l.size++
|
|||
|
}
|
|||
|
|
|||
|
// PushFront ajoute tous les éléments d’entrée en début de liste.
|
|||
|
func (l *List[T]) PushFront(elems ...T) {
|
|||
|
for _, e := range elems {
|
|||
|
l.push_front(e)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// PushBack ajoute tous les éléments d’entrée en fin de liste.
|
|||
|
func (l *List[T]) PushBack(elems ...T) {
|
|||
|
for _, e := range elems {
|
|||
|
l.push_back(e)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// PopFront supprime le premier élément de la liste.
|
|||
|
func (l *List[T]) PopFront() (e Option[T]) {
|
|||
|
if l.size > 0 {
|
|||
|
e = Some(l.first.value)
|
|||
|
l.first = l.first.next
|
|||
|
l.size--
|
|||
|
link(None[*dualChain[T]](), Some(l.first))
|
|||
|
if l.size == 0 {
|
|||
|
l.last = l.first
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// PopLast supprime le dernier élément de la liste.
|
|||
|
func (l *List[T]) PopLast() (e Option[T]) {
|
|||
|
if l.size > 0 {
|
|||
|
e = Some(l.last.value)
|
|||
|
l.last = l.last.prev
|
|||
|
l.size--
|
|||
|
link(Some(l.last), None[*dualChain[T]]())
|
|||
|
if l.size == 0 {
|
|||
|
l.first = l.last
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Concatenate concatène deux listes.
|
|||
|
func (q1 *List[T]) Concatenate(l2 *List[T]) {
|
|||
|
c, l := l2.first, l2.size
|
|||
|
for i := uint(0); i < l; i++ {
|
|||
|
q1.push_back(c.value)
|
|||
|
c = c.next
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// ToSlice convertit une liste en slice.
|
|||
|
func (l *List[T]) ToSlice() (sl []T) {
|
|||
|
sl = make([]T, l.size)
|
|||
|
c := l.first
|
|||
|
for i := uint(0); i < l.size; i++ {
|
|||
|
sl[i] = c.value
|
|||
|
c = c.next
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// NewList retourne une liste initialisée à partir des données d’entrées.
|
|||
|
func NewList[T any](elems ...T) (l *List[T]) {
|
|||
|
l = new(List[T])
|
|||
|
l.PushBack(elems...)
|
|||
|
|
|||
|
return
|
|||
|
}
|