focus/list/linkedlist/linkedlist.go

377 lines
6.3 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-21 06:28:08 +00:00
func (l *LinkedList) Find(every func(idx uint, value interface{}) bool) (interface{}, bool) {
idx := uint(0)
// 头部
for cur := l.head.next; cur != l.tail; cur = cur.next {
if every(idx, cur.value) {
return cur.value, true
}
idx++
}
return nil, false
}
func (l *LinkedList) FindMany(every func(idx uint, value interface{}) int) (result []interface{}, isfound bool) {
// the default of isfould is false
idx := uint(0)
// 头部
for cur := l.head.next; cur != l.tail; cur = cur.next {
j := every(idx, cur.value)
switch {
case j > 0:
result = append(result, cur.value)
isfound = true
case j < 0:
return result, isfound
}
idx++
}
return result, isfound
}
2019-05-19 18:14:46 +00:00
func (l *LinkedList) Index(idx uint) (interface{}, bool) {
if idx >= l.size {
return nil, false
}
if idx > l.size/2 {
idx = l.size - 1 - idx
// 尾部
2019-05-21 06:28:08 +00:00
for cur := l.tail.prev; cur != l.head; cur = cur.prev {
2019-05-19 18:14:46 +00:00
if idx == 0 {
return cur.value, true
}
idx--
}
} else {
// 头部
2019-05-21 06:28:08 +00:00
for cur := l.head.next; cur != l.tail; cur = cur.next {
2019-05-19 18:14:46 +00:00
if idx == 0 {
return cur.value, true
}
idx--
}
}
return nil, false
}
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) InsertIf(every func(idx uint, value interface{}) int, values ...interface{}) {
2019-05-19 18:14:46 +00:00
idx := uint(0)
// 头部
for cur := l.head.next; cur != nil; cur = cur.next {
isInsert := every(idx, cur.value)
if isInsert != 0 { // 1 为前 -1 为后 insert here(-1) ->cur-> insert here(1)
2019-05-19 18:14:46 +00:00
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
}
if isInsert < 0 {
cprev := cur.prev
cprev.next = start
start.prev = cprev
end.next = cur
cur.prev = end
} else {
cnext := cur.next
cnext.prev = end
start.prev = cur
cur.next = start
end.next = cnext
}
2019-05-19 18:14:46 +00:00
2019-05-21 06:28:08 +00:00
l.size += uint(len(values))
break
2019-05-19 18:14:46 +00:00
}
}
}
func remove(cur *Node) {
curPrev := cur.prev
curNext := cur.next
curPrev.next = curNext
curNext.prev = curPrev
cur.prev = nil
cur.next = nil
}
2019-05-19 18:14:46 +00:00
func (l *LinkedList) Remove(idx uint) (interface{}, bool) {
2019-05-17 11:54:55 +00:00
if idx >= l.size {
panic(fmt.Sprintf("out of list range, size is %d, idx is %d", l.size, idx))
}
2019-05-19 18:14:46 +00:00
2019-05-20 11:12:38 +00:00
l.size--
2019-05-19 18:14:46 +00:00
if idx > l.size/2 {
idx = l.size - idx // l.size - 1 - idx, 先减size
2019-05-19 18:14:46 +00:00
// 尾部
2019-05-21 06:28:08 +00:00
for cur := l.tail.prev; cur != l.head; cur = cur.prev {
2019-05-19 18:14:46 +00:00
if idx == 0 {
remove(cur)
2019-05-19 18:14:46 +00:00
return cur.value, true
}
idx--
2019-05-10 10:01:15 +00:00
}
2019-05-17 11:54:55 +00:00
2019-05-19 18:14:46 +00:00
} else {
// 头部
2019-05-21 06:28:08 +00:00
for cur := l.head.next; cur != l.tail; cur = cur.next {
2019-05-19 18:14:46 +00:00
if idx == 0 {
remove(cur)
2019-05-19 18:14:46 +00:00
return cur.value, true
2019-05-17 11:54:55 +00:00
}
idx--
}
2019-05-10 10:01:15 +00:00
}
2019-05-19 18:14:46 +00:00
panic(fmt.Sprintf("unknown error"))
2019-05-10 10:01:15 +00:00
}
2019-05-21 06:28:08 +00:00
func (l *LinkedList) RemoveIf(every func(idx uint, value interface{}) int) (result []interface{}, isRemoved bool) {
// 头部
2019-05-21 06:28:08 +00:00
idx := uint(0)
for cur := l.head.next; cur != l.tail; idx++ {
j := every(idx, cur.value)
switch {
case j > 0:
result = append(result, cur.value)
isRemoved = true
temp := cur.next
remove(cur)
2019-05-21 06:28:08 +00:00
cur = temp
l.size--
continue
case j < 0:
return
}
2019-05-21 06:28:08 +00:00
cur = cur.next
}
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
}
}
}