linkedlist finish; TODO: all list. add method with if
This commit is contained in:
parent
a02f238ff1
commit
632a3bd3ab
@ -224,14 +224,13 @@ func (l *LinkedList) Insert(idx uint, values ...interface{}) {
|
|||||||
l.size += uint(len(values))
|
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)
|
idx := uint(0)
|
||||||
// 头部
|
// 头部
|
||||||
for cur := l.head.next; cur != nil; cur = cur.next {
|
for cur := l.head.next; cur != nil; cur = cur.next {
|
||||||
|
isInsert := every(idx, cur.value)
|
||||||
if every(idx, cur) != 0 { // 1 为前 -1 为后
|
if isInsert != 0 { // 1 为前 -1 为后 insert here(-1) ->cur-> insert here(1)
|
||||||
|
|
||||||
var start *Node
|
var start *Node
|
||||||
var end *Node
|
var end *Node
|
||||||
|
|
||||||
@ -245,21 +244,36 @@ func (l *LinkedList) InsertIf(every func(idx uint, cur *Node) int, values ...int
|
|||||||
end = node
|
end = node
|
||||||
}
|
}
|
||||||
|
|
||||||
cprev := cur.prev
|
if isInsert < 0 {
|
||||||
|
cprev := cur.prev
|
||||||
cprev.next = start
|
cprev.next = start
|
||||||
start.prev = cprev
|
start.prev = cprev
|
||||||
|
end.next = cur
|
||||||
end.next = cur
|
cur.prev = end
|
||||||
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))
|
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) {
|
func (l *LinkedList) Remove(idx uint) (interface{}, bool) {
|
||||||
if idx >= l.size {
|
if idx >= l.size {
|
||||||
panic(fmt.Sprintf("out of list range, size is %d, idx is %d", l.size, idx))
|
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--
|
l.size--
|
||||||
if idx > l.size/2 {
|
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 {
|
for cur := l.tail.prev; cur != nil; cur = cur.prev {
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
curPrev := cur.prev
|
remove(cur)
|
||||||
curNext := cur.next
|
|
||||||
curPrev.next = curNext
|
|
||||||
curNext.prev = curPrev
|
|
||||||
cur.prev = nil
|
|
||||||
cur.next = nil
|
|
||||||
return cur.value, true
|
return cur.value, true
|
||||||
}
|
}
|
||||||
idx--
|
idx--
|
||||||
@ -286,12 +295,7 @@ func (l *LinkedList) Remove(idx uint) (interface{}, bool) {
|
|||||||
// 头部
|
// 头部
|
||||||
for cur := l.head.next; cur != nil; cur = cur.next {
|
for cur := l.head.next; cur != nil; cur = cur.next {
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
curPrev := cur.prev
|
remove(cur)
|
||||||
curNext := cur.next
|
|
||||||
curPrev.next = curNext
|
|
||||||
curNext.prev = curPrev
|
|
||||||
cur.prev = nil
|
|
||||||
cur.next = nil
|
|
||||||
return cur.value, true
|
return cur.value, true
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -302,6 +306,18 @@ func (l *LinkedList) Remove(idx uint) (interface{}, bool) {
|
|||||||
panic(fmt.Sprintf("unknown error"))
|
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{}) {
|
func (l *LinkedList) Values() (result []interface{}) {
|
||||||
l.Traversal(func(value interface{}) bool {
|
l.Traversal(func(value interface{}) bool {
|
||||||
result = append(result, value)
|
result = append(result, value)
|
||||||
|
@ -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) {
|
func TestIndex(t *testing.T) {
|
||||||
l := New()
|
l := New()
|
||||||
// "[4 3 2 1 0]"
|
// "[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)
|
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 != "<nil>" && l.Size() == 0 && len(l.Values()) == 0 {
|
||||||
|
t.Error("should be [3 2 1] but result is", result, "Size is", l.Size())
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err == nil {
|
if err := recover(); err == nil {
|
||||||
t.Error("should be out of range but is not")
|
t.Error("should be out of range but is not")
|
||||||
@ -207,6 +283,78 @@ func TestRemove(t *testing.T) {
|
|||||||
l.Remove(3)
|
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 != "<nil>" {
|
||||||
|
t.Error("result should be <nil>, but now result is", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkPushBack(b *testing.B) {
|
func BenchmarkPushBack(b *testing.B) {
|
||||||
|
|
||||||
ec := 5
|
ec := 5
|
||||||
|
Loading…
x
Reference in New Issue
Block a user