From 632a3bd3abf6abf48ba64dc698110931636bfc85 Mon Sep 17 00:00:00 2001 From: huangsimin Date: Tue, 21 May 2019 10:54:30 +0800 Subject: [PATCH] linkedlist finish; TODO: all list. add method with if --- list/linkedlist/linkedlist.go | 66 ++++++++----- list/linkedlist/linkedlist_test.go | 148 +++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 25 deletions(-) diff --git a/list/linkedlist/linkedlist.go b/list/linkedlist/linkedlist.go index 8e93337..dbc0121 100644 --- a/list/linkedlist/linkedlist.go +++ b/list/linkedlist/linkedlist.go @@ -224,14 +224,13 @@ func (l *LinkedList) Insert(idx uint, values ...interface{}) { l.size += uint(len(values)) } -func (l *LinkedList) InsertIf(every func(idx uint, cur *Node) int, values ...interface{}) { +func (l *LinkedList) InsertIf(every func(idx uint, value interface{}) int, values ...interface{}) { idx := uint(0) // 头部 for cur := l.head.next; cur != nil; cur = cur.next { - - if every(idx, cur) != 0 { // 1 为前 -1 为后 - + isInsert := every(idx, cur.value) + if isInsert != 0 { // 1 为前 -1 为后 insert here(-1) ->cur-> insert here(1) var start *Node var end *Node @@ -245,21 +244,36 @@ func (l *LinkedList) InsertIf(every func(idx uint, cur *Node) int, values ...int end = node } - cprev := cur.prev - - cprev.next = start - start.prev = cprev - - end.next = cur - cur.prev = end + 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 + } + break } - } l.size += uint(len(values)) } +func remove(cur *Node) { + curPrev := cur.prev + curNext := cur.next + curPrev.next = curNext + curNext.prev = curPrev + cur.prev = nil + cur.next = nil +} + 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)) @@ -267,16 +281,11 @@ func (l *LinkedList) Remove(idx uint) (interface{}, bool) { l.size-- if idx > l.size/2 { - idx = l.size - idx // l.size - 1 - idx + idx = l.size - idx // l.size - 1 - idx, 先减size // 尾部 for cur := l.tail.prev; cur != nil; cur = cur.prev { if idx == 0 { - curPrev := cur.prev - curNext := cur.next - curPrev.next = curNext - curNext.prev = curPrev - cur.prev = nil - cur.next = nil + remove(cur) return cur.value, true } idx-- @@ -286,12 +295,7 @@ func (l *LinkedList) Remove(idx uint) (interface{}, bool) { // 头部 for cur := l.head.next; cur != nil; cur = cur.next { if idx == 0 { - curPrev := cur.prev - curNext := cur.next - curPrev.next = curNext - curNext.prev = curPrev - cur.prev = nil - cur.next = nil + remove(cur) return cur.value, true } @@ -302,6 +306,18 @@ func (l *LinkedList) Remove(idx uint) (interface{}, bool) { panic(fmt.Sprintf("unknown error")) } +func (l *LinkedList) RemoveIf(every func(value interface{}) bool) (interface{}, bool) { + // 头部 + for cur := l.head.next; cur != nil; cur = cur.next { + if every(cur.value) { + remove(cur) + return cur.value, true + } + } + + return nil, false +} + func (l *LinkedList) Values() (result []interface{}) { l.Traversal(func(value interface{}) bool { result = append(result, value) diff --git a/list/linkedlist/linkedlist_test.go b/list/linkedlist/linkedlist_test.go index 9c6859e..59c0f3b 100644 --- a/list/linkedlist/linkedlist_test.go +++ b/list/linkedlist/linkedlist_test.go @@ -141,6 +141,64 @@ func TestInsert(t *testing.T) { } } +func TestInsertIf(t *testing.T) { + l := New() + + // "[4 3 2 1 0]" + for i := 0; i < 5; i++ { + l.Insert(0, i) + } + + // "[4 3 2 1 0]" + for i := 0; i < 2; i++ { + l.InsertIf(func(idx uint, value interface{}) int { + if value == 3 { + return 1 + } + return 0 + }, 11) + } + + var result string + + result = spew.Sprint(l.Values()) + if result != "[4 3 11 11 2 1 0]" { + t.Error("result should be [4 3 11 11 2 1 0], reuslt is", result) + } + + // "[4 3 2 1 0]" + for i := 0; i < 2; i++ { + l.InsertIf(func(idx uint, value interface{}) int { + if value == 0 { + return -1 + } + return 0 + }, 11) + } + + result = spew.Sprint(l.Values()) + if result != "[4 3 11 11 2 1 11 11 0]" { + t.Error("result should be [4 3 11 11 2 1 11 11 0], reuslt is", result) + } + + // "[4 3 2 1 0]" + for i := 0; i < 2; i++ { + l.InsertIf(func(idx uint, value interface{}) int { + if value == 0 { + return 1 + } + return 0 + }, 11) + } + + result = spew.Sprint(l.Values()) + if result != "[4 3 11 11 2 1 11 11 0 11 11]" { + t.Error("result should be [4 3 11 11 2 1 11 11 0 11 11], reuslt is", result) + } + + // t.Error(l.Values()) +} + func TestIndex(t *testing.T) { l := New() // "[4 3 2 1 0]" @@ -198,6 +256,24 @@ func TestRemove(t *testing.T) { t.Error("should be [3 2 1] but result is", result) } + l.Remove(2) + result = spew.Sprint(l.Values()) + if result != "[3 2]" { + t.Error("should be [3 2 1] but result is", result) + } + + l.Remove(1) + result = spew.Sprint(l.Values()) + if result != "[3]" { + t.Error("should be [3 2 1] but result is", result) + } + + l.Remove(0) + result = spew.Sprint(l.Values()) + if result != "" && l.Size() == 0 && len(l.Values()) == 0 { + 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") @@ -207,6 +283,78 @@ func TestRemove(t *testing.T) { l.Remove(3) } +func TestRemoveIf(t *testing.T) { + l := New() + // "[4 3 2 1 0]" + for i := 0; i < 5; i++ { + l.PushFront(i) + } + + if r, ok := l.RemoveIf(func(value interface{}) bool { + if value == 0 { + return true + } + return false + }); ok { + if r != 0 { + t.Error("result should is", 0) + } + } else { + t.Error("should be ok") + } + + if r, ok := l.RemoveIf(func(value interface{}) bool { + if value == 4 { + return true + } + return false + }); ok { + if r != 4 { + t.Error("result should is", 4) + } + } else { + t.Error("should be ok") + } + + var result string + result = spew.Sprint(l.Values()) + if result != "[3 2 1]" { + t.Error("should be [3 2 1] but result is", result) + } + + if r, ok := l.RemoveIf(func(value interface{}) bool { + if value == 4 { + return true + } + return false + }); ok { + t.Error("should not be ok and result is nil") + } else { + if r != nil { + t.Error("should be nil") + } + } + + result = spew.Sprint(l.Values()) + if result != "[3 2 1]" { + t.Error("should be [3 2 1] but result is", result) + } + + for _, v := range l.Values() { + l.RemoveIf(func(value interface{}) bool { + if value == v { + return true + } + return false + }) + } + + result = spew.Sprint(l.Values()) + if result != "" { + t.Error("result should be , but now result is", result) + } +} + func BenchmarkPushBack(b *testing.B) { ec := 5