1
0
mirror of https://github.com/charlienet/go-mixed.git synced 2025-07-18 00:22:41 +08:00
Files
go-mixed/collections/list/linked_list.go
2022-11-18 16:56:44 +08:00

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++
}