From 2b79a1acabfa322d64a06d834c944daaac5b59f2 Mon Sep 17 00:00:00 2001 From: huangsimin Date: Tue, 21 May 2019 14:28:08 +0800 Subject: [PATCH] fix some linkedlist bug --- list/linkedlist/linkedlist.go | 65 ++++++++++--- list/linkedlist/linkedlist_test.go | 149 +++++++++++++++++++++++++---- 2 files changed, 182 insertions(+), 32 deletions(-) diff --git a/list/linkedlist/linkedlist.go b/list/linkedlist/linkedlist.go index dbc0121..f939247 100644 --- a/list/linkedlist/linkedlist.go +++ b/list/linkedlist/linkedlist.go @@ -121,6 +121,37 @@ func (l *LinkedList) Back() (result interface{}, found bool) { return nil, false } +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 +} + func (l *LinkedList) Index(idx uint) (interface{}, bool) { if idx >= l.size { return nil, false @@ -129,7 +160,7 @@ func (l *LinkedList) Index(idx uint) (interface{}, bool) { if idx > l.size/2 { idx = l.size - 1 - idx // 尾部 - for cur := l.tail.prev; cur != nil; cur = cur.prev { + for cur := l.tail.prev; cur != l.head; cur = cur.prev { if idx == 0 { return cur.value, true } @@ -138,7 +169,7 @@ func (l *LinkedList) Index(idx uint) (interface{}, bool) { } else { // 头部 - for cur := l.head.next; cur != nil; cur = cur.next { + for cur := l.head.next; cur != l.tail; cur = cur.next { if idx == 0 { return cur.value, true } @@ -258,11 +289,10 @@ func (l *LinkedList) InsertIf(every func(idx uint, value interface{}) int, value end.next = cnext } + l.size += uint(len(values)) break } } - - l.size += uint(len(values)) } func remove(cur *Node) { @@ -283,7 +313,7 @@ func (l *LinkedList) Remove(idx uint) (interface{}, bool) { if idx > l.size/2 { idx = l.size - idx // l.size - 1 - idx, 先减size // 尾部 - for cur := l.tail.prev; cur != nil; cur = cur.prev { + for cur := l.tail.prev; cur != l.head; cur = cur.prev { if idx == 0 { remove(cur) return cur.value, true @@ -293,7 +323,7 @@ func (l *LinkedList) Remove(idx uint) (interface{}, bool) { } else { // 头部 - for cur := l.head.next; cur != nil; cur = cur.next { + for cur := l.head.next; cur != l.tail; cur = cur.next { if idx == 0 { remove(cur) return cur.value, true @@ -306,16 +336,27 @@ func (l *LinkedList) Remove(idx uint) (interface{}, bool) { panic(fmt.Sprintf("unknown error")) } -func (l *LinkedList) RemoveIf(every func(value interface{}) bool) (interface{}, bool) { +func (l *LinkedList) RemoveIf(every func(idx uint, value interface{}) int) (result []interface{}, isRemoved bool) { // 头部 - for cur := l.head.next; cur != nil; cur = cur.next { - if every(cur.value) { + 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) - return cur.value, true + cur = temp + l.size-- + continue + case j < 0: + return } - } - return nil, false + cur = cur.next + } + return } func (l *LinkedList) Values() (result []interface{}) { diff --git a/list/linkedlist/linkedlist_test.go b/list/linkedlist/linkedlist_test.go index 59c0f3b..4123794 100644 --- a/list/linkedlist/linkedlist_test.go +++ b/list/linkedlist/linkedlist_test.go @@ -199,6 +199,117 @@ func TestInsertIf(t *testing.T) { // t.Error(l.Values()) } +func TestFind(t *testing.T) { + l := New() + // "[4 3 2 1 0]" + for i := 0; i < 5; i++ { + l.PushFront(i) + } + + if v, isfound := l.Find(func(idx uint, value interface{}) bool { + if idx == 1 { + return true + } + return false + }); isfound { + if v != 3 { + t.Error("[4 3 2 1 0] index 1 shoud be 3 but value is", v) + } + } else { + t.Error("should be found") + } + + if v, isfound := l.Find(func(idx uint, value interface{}) bool { + if idx == 5 { + return true + } + return false + }); isfound { + t.Error("should not be found, but v is found, ", v) + } +} + +func TestFindMany(t *testing.T) { + l := New() + // "[4 3 2 1 0]" + for i := 0; i < 5; i++ { + l.PushFront(i) + } + + if values, isfound := l.FindMany(func(idx uint, value interface{}) int { + if idx >= 1 { + return 1 + } + return 0 + }); isfound { + var result string + result = spew.Sprint(values) + if result != "[3 2 1 0]" { + t.Error("result should be [3 2 1 0], reuslt is", result) + } + } else { + t.Error("should be found") + } + + if values, isfound := l.FindMany(func(idx uint, value interface{}) int { + if idx%2 == 0 { + return 1 + } + return 0 + }); isfound { + var result string + result = spew.Sprint(values) + if result != "[4 2 0]" { + t.Error("result should be [3 2 1 0], reuslt is", result) + } + } else { + t.Error("should be found") + } + + if values, isfound := l.FindMany(func(idx uint, value interface{}) int { + if value == 0 || value == 2 || value == 4 || value == 7 { + return 1 + } + return 0 + }); isfound { + var result string + result = spew.Sprint(values) + if result != "[4 2 0]" { + t.Error("result should be [4 2 0], reuslt is", result) + } + } else { + t.Error("should be found") + } + + if values, isfound := l.FindMany(func(idx uint, value interface{}) int { + if value.(int) <= 2 { + return -1 + } + + if value.(int) <= 4 && value.(int) > 2 { + return 1 + } + + return 0 + }); isfound { + var result string + result = spew.Sprint(values) + if result != "[4 3]" { + t.Error("result should be [4 2 0], reuslt is", result) + } + } else { + t.Error("should be found") + } + // if v, isfound := l.Find(func(idx uint, value interface{}) bool { + // if idx == 5 { + // return true + // } + // return false + // }); isfound { + // t.Error("should not be found, but v is found, ", v) + // } +} + func TestIndex(t *testing.T) { l := New() // "[4 3 2 1 0]" @@ -290,26 +401,26 @@ func TestRemoveIf(t *testing.T) { l.PushFront(i) } - if r, ok := l.RemoveIf(func(value interface{}) bool { + if result, ok := l.RemoveIf(func(idx uint, value interface{}) int { if value == 0 { - return true + return 1 } - return false + return 0 }); ok { - if r != 0 { + if result[0] != 0 { t.Error("result should is", 0) } } else { t.Error("should be ok") } - if r, ok := l.RemoveIf(func(value interface{}) bool { + if result, ok := l.RemoveIf(func(idx uint, value interface{}) int { if value == 4 { - return true + return 1 } - return false + return 0 }); ok { - if r != 4 { + if result[0] != 4 { t.Error("result should is", 4) } } else { @@ -322,15 +433,15 @@ func TestRemoveIf(t *testing.T) { t.Error("should be [3 2 1] but result is", result) } - if r, ok := l.RemoveIf(func(value interface{}) bool { + if result, ok := l.RemoveIf(func(idx uint, value interface{}) int { if value == 4 { - return true + return 1 } - return false + return 0 }); ok { t.Error("should not be ok and result is nil") } else { - if r != nil { + if result != nil { t.Error("should be nil") } } @@ -340,14 +451,12 @@ func TestRemoveIf(t *testing.T) { 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 - }) - } + l.RemoveIf(func(idx uint, value interface{}) int { + if value == 3 || value == 2 || value == 1 { + return 1 + } + return 0 + }) result = spew.Sprint(l.Values()) if result != "" {