完善: linkedlist

This commit is contained in:
huangsimin
2019-07-19 17:41:28 +08:00
parent 0fad6aae53
commit 76ca4e2a0e
7 changed files with 580 additions and 51 deletions

View File

@@ -0,0 +1,87 @@
package linkedlist
type Iterator struct {
ll *LinkedList
cur *Node
}
func (iter *Iterator) Value() interface{} {
return iter.cur.value
}
func (iter *Iterator) Prev() bool {
if iter.cur == iter.ll.head {
return false
}
iter.cur = iter.cur.prev
return iter.cur != iter.ll.head
}
func (iter *Iterator) Next() bool {
if iter.cur == iter.ll.tail {
return false
}
iter.cur = iter.cur.next
return iter.cur != iter.ll.tail
}
func (iter *Iterator) MoveToHead() {
iter.cur = iter.ll.head
}
func (iter *Iterator) MoveToTail() {
iter.cur = iter.ll.tail
}
type CircularIterator struct {
pl *LinkedList
cur *Node
}
func (iter *CircularIterator) Value() interface{} {
return iter.cur.value
}
func (iter *CircularIterator) Prev() bool {
if iter.pl.size == 0 {
return false
}
if iter.cur == iter.pl.head {
iter.cur = iter.pl.tail.prev
return true
}
iter.cur = iter.cur.prev
if iter.cur == iter.pl.head {
iter.cur = iter.pl.tail.prev
}
return true
}
func (iter *CircularIterator) Next() bool {
if iter.pl.size == 0 {
return false
}
if iter.cur == iter.pl.tail {
iter.cur = iter.pl.head.next
return true
}
iter.cur = iter.cur.next
if iter.cur == iter.pl.tail {
iter.cur = iter.pl.head.next
}
return true
}
func (iter *CircularIterator) MoveToHead() {
iter.cur = iter.pl.head
}
func (iter *CircularIterator) MoveToTail() {
iter.cur = iter.pl.tail
}

View File

@@ -1,6 +1,11 @@
package linkedlist
import "fmt"
import (
"fmt"
"log"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
prev *Node
@@ -18,12 +23,6 @@ type LinkedList struct {
size uint
}
// var nodePool *sync.Pool = &sync.Pool{
// New: func() interface{} {
// return &Node{}
// },
// }
func New() *LinkedList {
l := &LinkedList{}
l.head = &Node{}
@@ -37,6 +36,14 @@ func New() *LinkedList {
return l
}
func (l *LinkedList) Iterator() *Iterator {
return &Iterator{ll: l, cur: l.head}
}
func (l *LinkedList) CircularIterator() *CircularIterator {
return &CircularIterator{pl: l, cur: l.head}
}
func (l *LinkedList) Clear() {
l.head.next = nil
l.tail.prev = nil
@@ -191,7 +198,7 @@ func (l *LinkedList) Index(idx uint) (interface{}, bool) {
}
func (l *LinkedList) Insert(idx uint, values ...interface{}) {
if idx > l.size {
if idx > l.size { // 插入的方式 可能导致size的范围判断不一样
return
}
@@ -265,13 +272,37 @@ func (l *LinkedList) Insert(idx uint, values ...interface{}) {
l.size += uint(len(values))
}
func (l *LinkedList) InsertIf(every func(idx uint, value interface{}) int, values ...interface{}) {
// InsertState InsertIf的every函数的枚举 从左到右 1 为前 2 为后 insert here(2) ->cur-> insert here(1)
// UninsertAndContinue 不插入并且继续
// UninsertAndBreak 不插入并且停止
// InsertBack cur后插入并且停止
// InsertFront cur前插入并且停止
type InsertState int
const (
// UninsertAndContinue 不插入并且继续
UninsertAndContinue InsertState = 0
// UninsertAndBreak 不插入并且停止
UninsertAndBreak InsertState = -1
// InsertBack cur后插入并且停止
InsertBack InsertState = 2
// InsertFront cur前插入并且停止
InsertFront InsertState = 1
)
// InsertIf every函数的枚举 从左到右遍历 1 为前 2 为后 insert here(2) ->cur-> insert here(1)
func (l *LinkedList) InsertIf(every func(idx uint, value interface{}) InsertState, values ...interface{}) {
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)
insertState := every(idx, cur.value)
if insertState == UninsertAndContinue {
continue
}
if insertState > 0 { // 1 为前 2 为后 insert here(2) ->cur-> insert here(1)
var start *Node
var end *Node
@@ -285,13 +316,13 @@ func (l *LinkedList) InsertIf(every func(idx uint, value interface{}) int, value
end = node
}
if isInsert < 0 {
if insertState == InsertBack {
cprev := cur.prev
cprev.next = start
start.prev = cprev
end.next = cur
cur.prev = end
} else {
} else { // InsertFront
cnext := cur.next
cnext.prev = end
start.prev = cur
@@ -300,8 +331,11 @@ func (l *LinkedList) InsertIf(every func(idx uint, value interface{}) int, value
}
l.size += uint(len(values))
break
return
}
// 必然 等于 UninsertAndBreak
return
}
}
@@ -315,8 +349,9 @@ func remove(cur *Node) {
}
func (l *LinkedList) Remove(idx uint) (interface{}, bool) {
if idx >= l.size {
panic(fmt.Sprintf("out of list range, size is %d, idx is %d", l.size, idx))
if l.size <= idx {
log.Printf("out of list range, size is %d, idx is %d\n", l.size, idx)
return nil, false
}
l.size--
@@ -346,21 +381,50 @@ func (l *LinkedList) Remove(idx uint) (interface{}, bool) {
panic(fmt.Sprintf("unknown error"))
}
func (l *LinkedList) RemoveIf(every func(idx uint, value interface{}) int) (result []interface{}, isRemoved bool) {
// RemoveState RemoveIf的every函数的枚举
// RemoveAndContinue 删除并且继续
// RemoveAndBreak 删除并且停止
// UnremoveAndBreak 不删除并且停止遍历
// UnremoveAndContinue 不删除并且继续遍历
type RemoveState int
const (
// RemoveAndContinue 删除并且继续
RemoveAndContinue RemoveState = iota
// RemoveAndBreak 删除并且停止
RemoveAndBreak
// UnremoveAndBreak 不删除并且停止遍历
UnremoveAndBreak
// UnremoveAndContinue 不删除并且继续遍历
UnremoveAndContinue
)
// RemoveIf every的遍历函数操作remove过程 如果没删除result 返回nil, isRemoved = false
func (l *LinkedList) RemoveIf(every func(idx uint, value interface{}) RemoveState) (result []interface{}, isRemoved bool) {
// 头部
idx := uint(0)
TOPFOR:
for cur := l.head.next; cur != l.tail; idx++ {
j := every(idx, cur.value)
switch {
case j > 0:
removeState := every(idx, cur.value)
switch removeState {
case RemoveAndContinue:
result = append(result, cur.value)
isRemoved = true
temp := cur.next
remove(cur)
cur = temp
l.size--
continue
case j < 0:
continue TOPFOR
case RemoveAndBreak:
result = append(result, cur.value)
isRemoved = true
temp := cur.next
remove(cur)
cur = temp
l.size--
return
case UnremoveAndContinue:
case UnremoveAndBreak:
return
}
@@ -377,6 +441,10 @@ func (l *LinkedList) Values() (result []interface{}) {
return
}
func (l *LinkedList) String() string {
return spew.Sprint(l.Values())
}
func (l *LinkedList) Traversal(every func(interface{}) bool) {
for cur := l.head.next; cur != l.tail; cur = cur.next {
if !every(cur.value) {

View File

@@ -90,7 +90,28 @@ func TestPopBack(t *testing.T) {
}
func TestInsert(t *testing.T) {
func TestInsert2(t *testing.T) {
l := New()
// "[4 3 2 1 0]"
for i := 0; i < 5; i++ {
l.PushFront(0, i)
}
// step1: [0 0] -> step2: [1 0 0 0] front
if l.String() != "[4 0 3 0 2 0 1 0 0 0]" {
t.Error(l.String())
}
l.Insert(l.Size(), 5)
// step1: [0 0] -> step2: [4 0 3 0 2 0 1 0 0 0] front size is 10, but you can insert 11. equal to PushBack [4 0 3 0 2 0 1 0 0 0 5]
if l.String() != "[4 0 3 0 2 0 1 0 0 0 5]" {
t.Error(l.String())
}
}
func TestInsert1(t *testing.T) {
l1 := New()
l2 := New()
// "[4 3 2 1 0]"
@@ -149,13 +170,13 @@ func TestInsertIf(t *testing.T) {
l.Insert(0, i)
}
// "[4 3 2 1 0]"
// "[4 3 2 1 0]" 插入两个11
for i := 0; i < 2; i++ {
l.InsertIf(func(idx uint, value interface{}) int {
l.InsertIf(func(idx uint, value interface{}) InsertState {
if value == 3 {
return 1
return InsertFront
}
return 0
return UninsertAndContinue
}, 11)
}
@@ -168,11 +189,11 @@ func TestInsertIf(t *testing.T) {
// "[4 3 2 1 0]"
for i := 0; i < 2; i++ {
l.InsertIf(func(idx uint, value interface{}) int {
l.InsertIf(func(idx uint, value interface{}) InsertState {
if value == 0 {
return -1
return InsertBack
}
return 0
return UninsertAndContinue
}, 11)
}
@@ -183,11 +204,11 @@ func TestInsertIf(t *testing.T) {
// "[4 3 2 1 0]"
for i := 0; i < 2; i++ {
l.InsertIf(func(idx uint, value interface{}) int {
l.InsertIf(func(idx uint, value interface{}) InsertState {
if value == 0 {
return 1
return InsertFront
}
return 0
return UninsertAndContinue
}, 11)
}
@@ -385,13 +406,10 @@ func TestRemove(t *testing.T) {
t.Error("should be [3 2 1] but result is", result, "Size is", l.Size())
}
defer func() {
if err := recover(); err == nil {
t.Error("should be out of range but is not")
}
}()
if _, rvalue := l.Remove(3); rvalue != false {
t.Error("l is empty")
}
l.Remove(3)
}
func TestRemoveIf(t *testing.T) {
@@ -401,11 +419,11 @@ func TestRemoveIf(t *testing.T) {
l.PushFront(i)
}
if result, ok := l.RemoveIf(func(idx uint, value interface{}) int {
if result, ok := l.RemoveIf(func(idx uint, value interface{}) RemoveState {
if value == 0 {
return 1
return RemoveAndContinue
}
return 0
return UnremoveAndContinue
}); ok {
if result[0] != 0 {
t.Error("result should is", 0)
@@ -414,11 +432,11 @@ func TestRemoveIf(t *testing.T) {
t.Error("should be ok")
}
if result, ok := l.RemoveIf(func(idx uint, value interface{}) int {
if result, ok := l.RemoveIf(func(idx uint, value interface{}) RemoveState {
if value == 4 {
return 1
return RemoveAndContinue
}
return 0
return UnremoveAndContinue
}); ok {
if result[0] != 4 {
t.Error("result should is", 4)
@@ -433,11 +451,11 @@ func TestRemoveIf(t *testing.T) {
t.Error("should be [3 2 1] but result is", result)
}
if result, ok := l.RemoveIf(func(idx uint, value interface{}) int {
if result, ok := l.RemoveIf(func(idx uint, value interface{}) RemoveState {
if value == 4 {
return 1
return RemoveAndContinue
}
return 0
return UnremoveAndContinue
}); ok {
t.Error("should not be ok and result is nil")
} else {
@@ -451,17 +469,154 @@ func TestRemoveIf(t *testing.T) {
t.Error("should be [3 2 1] but result is", result)
}
l.RemoveIf(func(idx uint, value interface{}) int {
l.RemoveIf(func(idx uint, value interface{}) RemoveState {
if value == 3 || value == 2 || value == 1 {
return 1
return RemoveAndContinue
}
return 0
return UnremoveAndContinue
})
result = spew.Sprint(l.Values())
if result != "<nil>" {
t.Error("result should be <nil>, but now result is", result)
}
if results, ok := l.RemoveIf(func(idx uint, value interface{}) RemoveState {
if value == 3 || value == 2 || value == 1 {
return RemoveAndContinue
}
return UnremoveAndContinue
}); ok {
t.Error("why ok")
} else {
if results != nil {
t.Error(results)
}
}
}
func TestRemoveIf2(t *testing.T) {
l := New()
// "[4 3 2 1 0]"
for i := 0; i < 5; i++ {
l.PushFront(i)
}
for i := 0; i < 5; i++ {
l.PushFront(i)
}
// 只删除一个
if result, ok := l.RemoveIf(func(idx uint, value interface{}) RemoveState {
if value == 0 {
return RemoveAndBreak
}
return UnremoveAndContinue
}); ok {
if result[0] != 0 {
t.Error("result should is", 0)
}
} else {
t.Error("should be ok")
}
var resultstr string
resultstr = spew.Sprint(l.Values())
if resultstr != "[4 3 2 1 4 3 2 1 0]" {
t.Error("result should is", resultstr)
}
// 只删除多个
if result, ok := l.RemoveIf(func(idx uint, value interface{}) RemoveState {
if value == 4 {
return RemoveAndContinue
}
return UnremoveAndContinue
}); ok {
resultstr = spew.Sprint(result)
if resultstr != "[4 4]" {
t.Error("result should is", result)
}
resultstr = spew.Sprint(l.Values())
if resultstr != "[3 2 1 3 2 1 0]" {
t.Error("result should is", resultstr)
}
} else {
t.Error("should be ok")
}
}
func TestIterator(t *testing.T) {
ll := New()
for i := 0; i < 10; i++ {
ll.PushFront(i)
}
iter := ll.Iterator()
for i := 0; iter.Next(); i++ {
if iter.Value() != 9-i {
t.Error("iter.Next() ", iter.Value(), "is not equal ", 9-i)
}
}
if iter.cur != iter.ll.tail {
t.Error("current point is not equal tail ", iter.ll.tail)
}
for i := 0; iter.Prev(); i++ {
if iter.Value() != i {
t.Error("iter.Prev() ", iter.Value(), "is not equal ", i)
}
}
}
func TestCircularIterator(t *testing.T) {
ll := New()
for i := 0; i < 10; i++ {
ll.PushFront(i)
}
iter := ll.CircularIterator()
for i := 0; i != 10; i++ {
iter.Next()
if iter.Value() != 9-i {
t.Error("iter.Next() ", iter.Value(), "is not equal ", 9-i)
}
}
if iter.cur != iter.pl.tail.prev {
t.Error("current point is not equal tail ", iter.pl.tail.prev)
}
if iter.Next() {
if iter.Value() != 9 {
t.Error("iter.Value() != ", iter.Value())
}
}
iter.MoveToTail()
for i := 0; i != 10; i++ {
iter.Prev()
if iter.Value() != i {
t.Error("iter.Prev() ", iter.Value(), "is not equal ", i)
}
}
if iter.cur != iter.pl.head.next {
t.Error("current point is not equal tail ", iter.pl.tail.prev)
}
if iter.Prev() {
if iter.Value() != 0 {
t.Error("iter.Value() != ", iter.Value())
}
}
}
func BenchmarkPushBack(b *testing.B) {