285 lines
5.8 KiB
Go
285 lines
5.8 KiB
Go
// simple-list project slist.go
|
|
package kern
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
type ListNode struct {
|
|
data any
|
|
next *ListNode
|
|
}
|
|
|
|
func (node *ListNode) Next() *ListNode {
|
|
return node.next
|
|
}
|
|
|
|
func (self *ListNode) Data() any {
|
|
return self.data
|
|
}
|
|
|
|
type LinkedList struct {
|
|
count int
|
|
first *ListNode
|
|
last *ListNode
|
|
}
|
|
|
|
func NewLinkedList() (list *LinkedList) {
|
|
list = &LinkedList{0, nil, nil}
|
|
return
|
|
}
|
|
|
|
func (ls *LinkedList) Len() int {
|
|
return ls.count
|
|
}
|
|
|
|
func (ls *LinkedList) Empty() bool {
|
|
return ls.count == 0
|
|
}
|
|
|
|
func (ls *LinkedList) PushFront(data any) *ListNode {
|
|
ls.first = &ListNode{data, ls.first}
|
|
if ls.last == nil {
|
|
ls.last = ls.first
|
|
}
|
|
ls.count++
|
|
return ls.first
|
|
}
|
|
|
|
func (ls *LinkedList) SeqPushFront(data any) (result *LinkedList) {
|
|
switch seq := data.(type) {
|
|
case Iterator:
|
|
result = ls.IterPushFront(seq)
|
|
default:
|
|
ls.PushFront(data)
|
|
result = ls
|
|
}
|
|
return
|
|
}
|
|
|
|
func (ls *LinkedList) IterPushFront(it Iterator) *LinkedList {
|
|
for item, err1 := it.Next(); err1 == nil; item, err1 = it.Next() {
|
|
ls.PushFront(item)
|
|
}
|
|
return ls
|
|
}
|
|
|
|
func (ls *LinkedList) PushBack(data any) (node *ListNode) {
|
|
node = &ListNode{data, nil}
|
|
if ls.last != nil {
|
|
ls.last.next = node
|
|
}
|
|
ls.last = node
|
|
if ls.first == nil {
|
|
ls.first = node
|
|
}
|
|
ls.count++
|
|
return
|
|
}
|
|
|
|
func (ls *LinkedList) SeqPushBack(data any) (result *LinkedList) {
|
|
switch seq := data.(type) {
|
|
case Iterator:
|
|
result = ls.IterPushBack(seq)
|
|
default:
|
|
ls.PushBack(data)
|
|
result = ls
|
|
}
|
|
return
|
|
}
|
|
|
|
func (ls *LinkedList) IterPushBack(it Iterator) *LinkedList {
|
|
for item, err1 := it.Next(); err1 == nil; item, err1 = it.Next() {
|
|
ls.PushBack(item)
|
|
}
|
|
return ls
|
|
}
|
|
|
|
func (ls *LinkedList) FirstNode() *ListNode {
|
|
return ls.first
|
|
}
|
|
|
|
func (ls *LinkedList) First() (data any, err error) {
|
|
if ls.first != nil {
|
|
data = ls.first.data
|
|
} else {
|
|
err = errorListEmpty()
|
|
}
|
|
return
|
|
}
|
|
|
|
func (ls *LinkedList) LastNode() *ListNode {
|
|
return ls.last
|
|
}
|
|
|
|
func (ls *LinkedList) Last() (data interface{}, err error) {
|
|
if ls.last != nil {
|
|
data = ls.last.data
|
|
} else {
|
|
err = errorListEmpty()
|
|
}
|
|
return
|
|
}
|
|
|
|
func (ls *LinkedList) NodeAt(index int) (node *ListNode, err error) {
|
|
if ls.count == 0 {
|
|
err = errorListEmpty()
|
|
} else if index > ls.count {
|
|
err = errorOutOfRange()
|
|
} else if index == ls.count-1 {
|
|
node = ls.last
|
|
} else {
|
|
current := ls.first
|
|
for range index {
|
|
current = current.next
|
|
}
|
|
node = current
|
|
}
|
|
return
|
|
}
|
|
|
|
func (ls *LinkedList) At(index int) (data interface{}, err error) {
|
|
node, err := ls.NodeAt(index)
|
|
if err == nil {
|
|
data = node.data
|
|
}
|
|
return
|
|
}
|
|
|
|
func (ls *LinkedList) Insert(index int, data any) *ListNode {
|
|
var prev *ListNode
|
|
|
|
prev = nil
|
|
current := ls.first
|
|
for pos := 0; current != nil && pos < index; pos++ {
|
|
prev = current
|
|
current = current.next
|
|
}
|
|
|
|
node := &ListNode{data, current}
|
|
|
|
if prev != nil {
|
|
prev.next = node
|
|
}
|
|
|
|
if ls.first == current {
|
|
ls.first = node
|
|
}
|
|
if node.next == nil {
|
|
ls.last = node
|
|
}
|
|
ls.count++
|
|
return node
|
|
}
|
|
|
|
func (ls *LinkedList) PushBackStringArray(items []string) {
|
|
for _, v := range items {
|
|
ls.PushBack(v)
|
|
}
|
|
}
|
|
|
|
func (ls *LinkedList) Sub(start, end int) (subList *LinkedList) {
|
|
subList = NewLinkedList()
|
|
if node, err := ls.NodeAt(start); err == nil {
|
|
for i := start; i < end && node != nil; i++ {
|
|
subList.PushBack(node.data)
|
|
node = node.next
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// type TraverseOperator func(index int, elem interface{}, userData interface{}) (err error)
|
|
|
|
// func (self *LinkedList) Traverse(op TraverseOperator, user_data interface{}) (err error) {
|
|
// index := int(0)
|
|
// for current := self.first; current != nil; current = current.next {
|
|
// err = op(index, current.data, user_data)
|
|
// if err != nil {
|
|
// break
|
|
// }
|
|
// index++
|
|
// }
|
|
// return
|
|
// }
|
|
|
|
// func (self *LinkedList) Traverse2(observer Observer, abortOnError bool) (err error) {
|
|
// index := int(0)
|
|
// for current := self.first; current != nil; current = current.next {
|
|
// err = observer.Observe(current, index)
|
|
// if err != nil && abortOnError {
|
|
// break
|
|
// }
|
|
// index++
|
|
// }
|
|
// return
|
|
// }
|
|
|
|
type EqualFunc func(current, target any) bool
|
|
|
|
func (ls *LinkedList) FindFirst(eqFunc EqualFunc, targetData any) (targetNode *ListNode) {
|
|
for current := ls.first; current != nil && targetNode == nil; current = current.next {
|
|
if eqFunc(current.data, targetData) {
|
|
targetNode = current
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (ls *LinkedList) FindNext(eqFunc EqualFunc, startNode *ListNode) (targetNode *ListNode) {
|
|
if startNode != nil {
|
|
for current := startNode.next; current != nil && targetNode == nil; current = current.next {
|
|
if eqFunc(current.data, startNode.Data()) {
|
|
targetNode = current
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// type DataFeeder func(user_data interface{}) interface{}
|
|
// type NodeObserver func(node *ListNode, index int, userData interface{})
|
|
|
|
// func (self *LinkedList) FeedTail(feeder DataFeeder, feederUserData interface{}, observer NodeObserver, observerUserData interface{}) (count int) {
|
|
// count = 0
|
|
// for item := feeder(feederUserData); item != nil; item = feeder(feederUserData) {
|
|
// // fmt.Println("Item", count, item)
|
|
// node := self.PushBack(item)
|
|
// if observer != nil {
|
|
// observer(node, count, observerUserData)
|
|
// }
|
|
// count++
|
|
// }
|
|
// return
|
|
// }
|
|
|
|
// func (self *LinkedList) FeedTail2(feeder Feeder, observer Observer, abortOnError bool) (count int, err error) {
|
|
// count = 0
|
|
// // item := feeder.Next()
|
|
// for item, err1 := feeder.Next(); item != nil; item, err1 = feeder.Next() {
|
|
// if err1 != nil {
|
|
// if err == nil {
|
|
// err = err1
|
|
// }
|
|
// if abortOnError {
|
|
// break
|
|
// }
|
|
// }
|
|
// // fmt.Println("Item", count, item)
|
|
// node := self.PushBack(item)
|
|
// if observer != nil {
|
|
// observer.Observe(node, count)
|
|
// }
|
|
// count++
|
|
// }
|
|
// return
|
|
// }
|
|
|
|
func errorListEmpty() error {
|
|
return fmt.Errorf("List is empty")
|
|
}
|
|
|
|
func errorOutOfRange() error {
|
|
return fmt.Errorf("Out of range")
|
|
}
|