mirror of
https://github.com/charlienet/go-mixed.git
synced 2025-07-18 00:22:41 +08:00
163 lines
2.4 KiB
Go
163 lines
2.4 KiB
Go
package list
|
|
|
|
import (
|
|
"github.com/charlienet/go-mixed/locker"
|
|
)
|
|
|
|
type LinkedList[T any] struct {
|
|
list[T]
|
|
front, tail *LinkedNode[T]
|
|
}
|
|
|
|
type LinkedNode[T any] struct {
|
|
Value T
|
|
Prev, Next *LinkedNode[T]
|
|
}
|
|
|
|
func NewLinkedList[T any](elems ...T) *LinkedList[T] {
|
|
l :=
|
|
&LinkedList[T]{
|
|
list: list[T]{locker: locker.EmptyLocker},
|
|
}
|
|
|
|
for _, e := range elems {
|
|
l.pushBackNode(&LinkedNode[T]{Value: e})
|
|
}
|
|
|
|
return l
|
|
}
|
|
|
|
func (l *LinkedList[T]) PushBack(v T) *LinkedList[T] {
|
|
l.pushBackNode(&LinkedNode[T]{Value: v})
|
|
|
|
return l
|
|
}
|
|
|
|
func (l *LinkedList[T]) PushFront(v T) *LinkedList[T] {
|
|
l.pushFrontNode(&LinkedNode[T]{Value: v})
|
|
|
|
return l
|
|
}
|
|
|
|
func (l *LinkedList[T]) FrontNode() *LinkedNode[T] {
|
|
return l.front
|
|
}
|
|
|
|
func (l *LinkedList[T]) Front() T {
|
|
return l.FrontNode().Value
|
|
}
|
|
|
|
func (l *LinkedList[T]) BackNode() *LinkedNode[T] {
|
|
return l.tail
|
|
}
|
|
|
|
func (l *LinkedList[T]) Back() T {
|
|
if l.size == 0 {
|
|
panic(ErrorOutOffRange)
|
|
}
|
|
return l.tail.Value
|
|
}
|
|
|
|
func (l *LinkedList[T]) ForEach(fn func(T) bool) {
|
|
l.locker.RLock()
|
|
defer l.locker.RUnlock()
|
|
|
|
for current := l.front; current != nil; current = current.Next {
|
|
if fn(current.Value) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func (l *LinkedList[T]) GetAt(i int) T {
|
|
if i <= l.Size() {
|
|
var n int
|
|
for current := l.front; current != nil; current = current.Next {
|
|
if n == i {
|
|
return current.Value
|
|
}
|
|
n++
|
|
}
|
|
}
|
|
|
|
return *new(T)
|
|
}
|
|
|
|
func (l *LinkedList[T]) Remove(n *LinkedNode[T]) {
|
|
l.locker.Lock()
|
|
defer l.locker.Unlock()
|
|
|
|
if n.Next != nil {
|
|
n.Next.Prev = n.Prev
|
|
} else {
|
|
l.tail = n.Prev
|
|
}
|
|
|
|
if n.Prev != nil {
|
|
n.Prev.Next = n.Next
|
|
} else {
|
|
l.front = n.Next
|
|
}
|
|
|
|
l.size--
|
|
}
|
|
|
|
func (l *LinkedList[T]) RemoveAt(index int) {
|
|
l.locker.Lock()
|
|
defer l.locker.Unlock()
|
|
|
|
var i int
|
|
var prev *LinkedNode[T]
|
|
|
|
prev = l.front
|
|
for current := l.front; current != nil; {
|
|
|
|
if i == index {
|
|
prev.Next = current.Next
|
|
current.Next = nil
|
|
|
|
l.size--
|
|
return
|
|
}
|
|
|
|
prev = current
|
|
current = current.Next
|
|
i++
|
|
}
|
|
|
|
}
|
|
|
|
func (l *LinkedList[T]) pushBackNode(n *LinkedNode[T]) {
|
|
l.locker.Lock()
|
|
defer l.locker.Unlock()
|
|
|
|
n.Next = nil
|
|
n.Prev = l.tail
|
|
|
|
if l.tail != nil {
|
|
l.tail.Next = n
|
|
} else {
|
|
l.front = n
|
|
}
|
|
|
|
l.tail = n
|
|
|
|
l.size++
|
|
}
|
|
|
|
func (l *LinkedList[T]) pushFrontNode(n *LinkedNode[T]) {
|
|
l.locker.Lock()
|
|
defer l.locker.Unlock()
|
|
|
|
n.Next = l.front
|
|
n.Prev = nil
|
|
if l.front != nil {
|
|
l.front.Prev = n
|
|
} else {
|
|
l.tail = n
|
|
}
|
|
l.front = n
|
|
|
|
l.size++
|
|
}
|