focus/list/linkedlist/linkedlist.go

243 lines
3.7 KiB
Go
Raw Normal View History

2019-05-10 10:01:15 +00:00
package linkedlist
2019-05-17 11:54:55 +00:00
import "fmt"
2019-05-10 10:01:15 +00:00
type Node struct {
2019-05-17 11:54:55 +00:00
prev *Node
2019-05-10 10:01:15 +00:00
next *Node
value interface{}
}
func (node *Node) Value() interface{} {
return node.value
}
type LinkedList struct {
head *Node
2019-05-17 11:54:55 +00:00
tail *Node
2019-05-10 10:01:15 +00:00
size uint
}
2019-05-17 11:54:55 +00:00
// var nodePool *sync.Pool = &sync.Pool{
// New: func() interface{} {
// return &Node{}
// },
// }
2019-05-10 10:01:15 +00:00
func New() *LinkedList {
2019-05-17 11:54:55 +00:00
l := &LinkedList{}
l.head = &Node{}
l.head.prev = nil
l.tail = &Node{}
l.tail.next = nil
l.head.next = l.tail
l.tail.prev = l.head
return l
2019-05-10 10:01:15 +00:00
}
func (l *LinkedList) Size() uint {
return l.size
}
2019-05-17 11:54:55 +00:00
func (l *LinkedList) PushFront(values ...interface{}) {
var node *Node
l.size += uint(len(values))
for _, v := range values {
node = &Node{}
node.value = v
hnext := l.head.next
hnext.prev = node
node.next = hnext
node.prev = l.head
l.head.next = node
2019-05-10 10:01:15 +00:00
}
}
2019-05-17 11:54:55 +00:00
func (l *LinkedList) PushBack(values ...interface{}) {
var node *Node
l.size += uint(len(values))
for _, v := range values {
node = &Node{}
node.value = v
tprev := l.tail.prev
tprev.next = node
2019-05-10 10:01:15 +00:00
2019-05-17 11:54:55 +00:00
node.prev = tprev
node.next = l.tail
l.tail.prev = node
}
2019-05-10 10:01:15 +00:00
}
2019-05-17 11:54:55 +00:00
func (l *LinkedList) PopFront() (result interface{}, found bool) {
if l.size != 0 {
l.size--
temp := l.head.next
hnext := temp.next
hnext.prev = l.head
l.head.next = hnext
result = temp.value
found = true
return
2019-05-10 10:01:15 +00:00
}
return nil, false
}
2019-05-17 11:54:55 +00:00
func (l *LinkedList) PopBack() (result interface{}, found bool) {
if l.size != 0 {
l.size--
temp := l.tail.prev
tprev := temp.prev
tprev.next = l.tail
l.tail.prev = tprev
result = temp.value
found = true
return
2019-05-10 10:01:15 +00:00
}
2019-05-17 11:54:55 +00:00
return nil, false
}
2019-05-10 10:01:15 +00:00
2019-05-17 11:54:55 +00:00
func (l *LinkedList) Front() (result interface{}, found bool) {
if l.size != 0 {
return l.head.next.value, true
}
return nil, false
2019-05-10 10:01:15 +00:00
}
2019-05-17 11:54:55 +00:00
func (l *LinkedList) Back() (result interface{}, found bool) {
if l.size != 0 {
return l.tail.prev.value, true
2019-05-10 10:01:15 +00:00
}
2019-05-17 11:54:55 +00:00
return nil, false
}
2019-05-10 10:01:15 +00:00
2019-05-17 11:54:55 +00:00
func (l *LinkedList) Insert(idx uint, values ...interface{}) {
if idx > l.size {
2019-05-10 10:01:15 +00:00
return
}
2019-05-17 11:54:55 +00:00
if idx > l.size/2 {
idx = l.size - idx
// 尾部
for cur := l.tail.prev; cur != nil; cur = cur.prev {
if idx == 0 {
var start *Node
var end *Node
start = &Node{value: values[0]}
end = start
for _, value := range values[1:] {
node := &Node{value: value}
end.next = node
node.prev = end
end = node
}
cnext := cur.next
cur.next = start
start.prev = cur
end.next = cnext
cnext.prev = end
break
}
idx--
}
} else {
// 头部
for cur := l.head.next; cur != nil; cur = cur.next {
if idx == 0 {
var start *Node
var end *Node
start = &Node{value: values[0]}
end = start
for _, value := range values[1:] {
node := &Node{value: value}
end.next = node
node.prev = end
end = node
}
cprev := cur.prev
cprev.next = start
start.prev = cprev
end.next = cur
cur.prev = end
break
}
idx--
}
}
l.size += uint(len(values))
}
func (l *LinkedList) Remove(idx uint) {
if idx >= l.size {
panic(fmt.Sprintf("out of list range, size is %d, idx is %d", l.size, idx))
}
if l.head != nil {
if idx == 0 {
2019-05-10 10:01:15 +00:00
l.size--
2019-05-17 11:54:55 +00:00
temp := l.head
l.head = l.head.next
nodePool.Put(temp)
2019-05-10 10:01:15 +00:00
return
}
2019-05-17 11:54:55 +00:00
for cur := l.head; cur.next != nil; cur = cur.next {
if idx == 1 {
l.size--
result := cur.next
cur.next = result.next
result.next = nil
nodePool.Put(result)
return
}
idx--
}
2019-05-10 10:01:15 +00:00
}
2019-05-17 11:54:55 +00:00
return
2019-05-10 10:01:15 +00:00
}
func (l *LinkedList) Values() (result []interface{}) {
2019-05-17 11:54:55 +00:00
l.Traversal(func(value interface{}) bool {
result = append(result, value)
2019-05-10 10:01:15 +00:00
return true
})
return
}
2019-05-17 11:54:55 +00:00
func (l *LinkedList) Traversal(every func(interface{}) bool) {
for cur := l.head.next; cur != l.tail; cur = cur.next {
if !every(cur.value) {
2019-05-10 10:01:15 +00:00
break
}
}
}