2021-05-20 17:32:35 +08:00
|
|
|
package collections
|
|
|
|
|
|
|
|
import (
|
2021-05-21 09:48:33 +08:00
|
|
|
"github.com/tursom/GoCollections/exceptions"
|
2021-05-20 17:32:35 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
LinkedList struct {
|
|
|
|
head *linkedListNode
|
|
|
|
size uint32
|
|
|
|
}
|
|
|
|
linkedListNode struct {
|
|
|
|
prev, next *linkedListNode
|
|
|
|
value interface{}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func (l LinkedList) String() string {
|
|
|
|
return String(l)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewLinkedList() *LinkedList {
|
|
|
|
tail := &linkedListNode{}
|
|
|
|
tail.prev = tail
|
|
|
|
tail.next = tail
|
|
|
|
return &LinkedList{tail, 0}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l LinkedList) Size() uint32 {
|
|
|
|
return l.size
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l LinkedList) IsEmpty() bool {
|
|
|
|
return l.size == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l LinkedList) Contains(element interface{}) bool {
|
|
|
|
return Contains(&l, element)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l LinkedList) ContainsAll(c Collection) bool {
|
|
|
|
return ContainsAll(&l, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LinkedList) Add(element interface{}) bool {
|
|
|
|
l.size++
|
|
|
|
node := &linkedListNode{l.head.prev, l.head, element}
|
|
|
|
node.next.prev = node
|
|
|
|
node.prev.next = node
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2021-05-21 09:41:58 +08:00
|
|
|
func (l *LinkedList) Remove(element interface{}) error {
|
|
|
|
err := LoopMutable(l, func(e interface{}, iterator MutableIterator) error {
|
2021-05-20 17:32:35 +08:00
|
|
|
if element == e {
|
|
|
|
iterator.Remove()
|
|
|
|
return exceptions.CollectionLoopFinished
|
|
|
|
}
|
|
|
|
return nil
|
2021-05-21 09:41:58 +08:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
return exceptions.NewElementNotFoundException("", true)
|
|
|
|
}
|
2021-05-20 17:32:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LinkedList) AddAll(c Collection) bool {
|
|
|
|
return AddAll(l, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LinkedList) RemoveAll(c Collection) bool {
|
|
|
|
return RemoveAll(l, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LinkedList) RetainAll(c Collection) bool {
|
|
|
|
return RetainAll(l, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LinkedList) Clear() {
|
|
|
|
l.head.next = l.head
|
|
|
|
l.size = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l LinkedList) SubList(from, to uint32) List {
|
|
|
|
return NewSubList(l, from, to)
|
|
|
|
}
|
|
|
|
|
2021-05-21 09:41:58 +08:00
|
|
|
func (l *LinkedList) Set(index uint32, element interface{}) error {
|
2021-05-20 17:32:35 +08:00
|
|
|
node := l.head
|
|
|
|
for node != l.head {
|
|
|
|
if index == 0 {
|
|
|
|
node.value = element
|
2021-05-21 09:41:58 +08:00
|
|
|
return nil
|
2021-05-20 17:32:35 +08:00
|
|
|
}
|
|
|
|
index--
|
|
|
|
}
|
2021-05-21 09:41:58 +08:00
|
|
|
return exceptions.NewIndexOutOfBound("", true)
|
2021-05-20 17:32:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LinkedList) AddAtIndex(index uint32, element interface{}) bool {
|
|
|
|
node := l.head
|
|
|
|
for node != l.head {
|
|
|
|
if index == 0 {
|
|
|
|
l.size++
|
|
|
|
node.next = &linkedListNode{node, node.next, element}
|
|
|
|
node.next.next.prev = node.next
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
index--
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-05-21 10:31:49 +08:00
|
|
|
func (l *LinkedList) RemoveAt(index uint32) error {
|
2021-05-20 17:32:35 +08:00
|
|
|
node := l.head
|
|
|
|
for node != l.head {
|
|
|
|
if index == 0 {
|
|
|
|
l.size--
|
|
|
|
node.remove()
|
2021-05-21 10:31:49 +08:00
|
|
|
return nil
|
2021-05-20 17:32:35 +08:00
|
|
|
}
|
|
|
|
index--
|
|
|
|
}
|
2021-05-21 10:31:49 +08:00
|
|
|
return exceptions.NewIndexOutOfBound("", true)
|
2021-05-20 17:32:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LinkedList) SubMutableList(from, to uint32) MutableList {
|
|
|
|
return NewMutableSubList(l, from, to)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l LinkedList) Get(index uint32) (interface{}, error) {
|
|
|
|
node := l.head
|
|
|
|
for node != l.head {
|
|
|
|
if index == 0 {
|
|
|
|
return node.value, nil
|
|
|
|
}
|
|
|
|
index--
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, exceptions.NewIndexOutOfBound("", true)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l LinkedList) Iterator() Iterator {
|
|
|
|
return l.MutableIterator()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LinkedList) MutableIterator() MutableIterator {
|
|
|
|
return &linkedListIterator{l, l.head.next, l.head}
|
|
|
|
}
|
|
|
|
|
|
|
|
type linkedListIterator struct {
|
|
|
|
list *LinkedList
|
|
|
|
node, head *linkedListNode
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *linkedListIterator) HasNext() bool {
|
|
|
|
return l.node != l.head
|
|
|
|
}
|
|
|
|
|
2021-05-21 09:41:58 +08:00
|
|
|
func (l *linkedListIterator) Next() (interface{}, error) {
|
2021-05-20 17:32:35 +08:00
|
|
|
if l.node == l.head {
|
2021-05-21 09:41:58 +08:00
|
|
|
return nil, exceptions.NewIndexOutOfBound("", true)
|
2021-05-20 17:32:35 +08:00
|
|
|
}
|
|
|
|
l.node = l.node.next
|
2021-05-21 09:41:58 +08:00
|
|
|
return l.node.prev.value, nil
|
2021-05-20 17:32:35 +08:00
|
|
|
}
|
|
|
|
|
2021-05-21 10:31:49 +08:00
|
|
|
func (l *linkedListIterator) Remove() error {
|
2021-05-20 17:32:35 +08:00
|
|
|
if l.node.prev == l.head {
|
2021-05-21 10:31:49 +08:00
|
|
|
return exceptions.NewIndexOutOfBound("", true)
|
2021-05-20 17:32:35 +08:00
|
|
|
}
|
|
|
|
l.node.prev.remove()
|
|
|
|
l.list.size--
|
2021-05-21 10:31:49 +08:00
|
|
|
return nil
|
2021-05-20 17:32:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *linkedListNode) remove() {
|
|
|
|
l.next.prev = l.prev
|
|
|
|
l.prev.next = l.next
|
|
|
|
}
|