diff --git a/for_test.go b/for_test.go index d2d038e..f9958d6 100644 --- a/for_test.go +++ b/for_test.go @@ -1,4 +1,4 @@ -package structure +package focus import ( "bytes" diff --git a/interface.go b/interface.go index 6fe4564..c3a3474 100644 --- a/interface.go +++ b/interface.go @@ -1 +1 @@ -package structure +package focus diff --git a/list/array_list/array_list.go b/list/array_list/array_list.go index 8b2aa7f..3dc18ca 100644 --- a/list/array_list/array_list.go +++ b/list/array_list/array_list.go @@ -1,6 +1,10 @@ package arraylist -import "log" +import ( + "log" + + "github.com/474420502/focus/list" +) type ArrayList struct { data []interface{} @@ -12,6 +16,11 @@ type ArrayList struct { shrinkSize uint } +func assertImplementation() { + var _ list.IList = (*ArrayList)(nil) + var _ list.ILinkedList = (*ArrayList)(nil) +} + const ( listMaxLimit = uint(1) << 63 listMinLimit = uint(8) @@ -28,6 +37,14 @@ func New() *ArrayList { return l } +func (l *ArrayList) Iterator() *Iterator { + return &Iterator{al: l, cur: 0, isInit: false} +} + +func (l *ArrayList) CircularIterator() *CircularIterator { + return &CircularIterator{al: l, cur: 0, isInit: false} +} + func (l *ArrayList) Clear() { l.data = make([]interface{}, 8, 8) l.tidx = initCap / 2 @@ -83,6 +100,15 @@ func (l *ArrayList) growth() { } +func (l *ArrayList) Push(value interface{}) { + for l.tidx+1 > uint(len(l.data)) { + l.growth() + } + l.data[l.tidx] = value + l.tidx++ + l.size += 1 +} + func (l *ArrayList) PushFront(values ...interface{}) { psize := uint(len(values)) for l.hidx+1-psize > listMaxLimit { @@ -183,3 +209,11 @@ func (l *ArrayList) Values() []interface{} { copy(newElements, l.data[l.hidx+1:l.tidx]) return newElements } + +func (l *ArrayList) Traversal(every func(interface{}) bool) { + for i := uint(0); i < l.size; i++ { + if !every(l.data[i+l.hidx+1]) { + break + } + } +} diff --git a/list/array_list/array_list_test.go b/list/array_list/array_list_test.go index 1054b60..2785d66 100644 --- a/list/array_list/array_list_test.go +++ b/list/array_list/array_list_test.go @@ -10,6 +10,67 @@ import ( "github.com/davecgh/go-spew/spew" ) +func TestIterator(t *testing.T) { + l := New() + + for i := 0; i < 5; i++ { + l.Push(i) + } + + iter := l.Iterator() + + var result []int + for iter.Next() { + result = append(result, iter.Value().(int)) + } + + if spew.Sprint(result) != "[0 1 2 3 4]" { + t.Error(result) + } + + iter = l.Iterator() + result = nil + for iter.Prev() { + result = append(result, iter.Value().(int)) + } + + if spew.Sprint(result) != "[4 3 2 1 0]" { + t.Error(result) + } + + citer := l.CircularIterator() + result = nil + for i := 0; i < 11; i++ { + if citer.Next() { + result = append(result, citer.Value().(int)) + } + } + + if len(result) != 11 { + t.Error("len(result) != 11, is ", len(result)) + } + + if spew.Sprint(result) != "[0 1 2 3 4 0 1 2 3 4 0]" { + t.Error(result) + } + + citer = l.CircularIterator() + result = nil + for i := 0; i < 11; i++ { + if citer.Prev() { + result = append(result, citer.Value().(int)) + } + } + + if len(result) != 11 { + t.Error("len(result) != 11, is ", len(result)) + } + + if spew.Sprint(result) != "[4 3 2 1 0 4 3 2 1 0 4]" { + t.Error(result) + } +} + func TestPush(t *testing.T) { l := New() @@ -30,6 +91,12 @@ func TestPush(t *testing.T) { t.Error(result) } + l.Push(3) + result = spew.Sprint(l.Values()) + if result != "[1 1 2 2 3]" { + t.Error(result) + } + } func TestGrowth(t *testing.T) { @@ -148,6 +215,35 @@ func TestRemove(t *testing.T) { } +func TestTraversal(t *testing.T) { + l := New() + for i := 0; i < 5; i++ { + l.PushFront(uint(i)) + } + + var result []interface{} + + l.Traversal(func(v interface{}) bool { + result = append(result, v) + return true + }) + + if spew.Sprint(result) != "[4 3 2 1 0]" { + t.Error(result) + } + + l.PushBack(7, 8) + result = nil + l.Traversal(func(v interface{}) bool { + result = append(result, v) + return true + }) + + if spew.Sprint(result) != "[4 3 2 1 0 7 8]" { + t.Error(result) + } +} + func loadTestData() []int { data, err := ioutil.ReadFile("../../l.log") if err != nil { diff --git a/list/array_list/iterator.go b/list/array_list/iterator.go new file mode 100644 index 0000000..fc3acdd --- /dev/null +++ b/list/array_list/iterator.go @@ -0,0 +1,125 @@ +package arraylist + +type Iterator struct { + al *ArrayList + cur uint + isInit bool +} + +func (iter *Iterator) Value() interface{} { + v, _ := iter.al.Index(iter.cur) + return v +} + +func (iter *Iterator) Prev() bool { + + if iter.isInit == false { + if iter.al.size != 0 { + iter.isInit = true + iter.cur = iter.al.size - 1 + return true + } + return false + } + + if iter.cur <= 0 { + return false + } + iter.cur-- + return true +} + +func (iter *Iterator) Next() bool { + + if iter.isInit == false { + if iter.al.size != 0 { + iter.isInit = true + iter.cur = 0 + return true + } + return false + } + + if iter.cur >= iter.al.size-1 { + return false + } + iter.cur++ + return true +} + +func (iter *Iterator) ToHead() { + iter.isInit = true + iter.cur = 0 +} + +func (iter *Iterator) ToTail() { + iter.isInit = true + iter.cur = iter.al.size - 1 +} + +type CircularIterator struct { + al *ArrayList + cur uint + isInit bool +} + +func (iter *CircularIterator) Value() interface{} { + v, _ := iter.al.Index(iter.cur) + return v +} + +func (iter *CircularIterator) Prev() bool { + + if iter.isInit == false { + if iter.al.size != 0 { + iter.isInit = true + iter.cur = iter.al.size - 1 + return true + } + return false + } + + if iter.al.size == 0 { + return false + } + + if iter.cur <= 0 { + iter.cur = iter.al.size - 1 + } else { + iter.cur-- + } + return true +} + +func (iter *CircularIterator) Next() bool { + + if iter.isInit == false { + if iter.al.size != 0 { + iter.isInit = true + iter.cur = 0 + return true + } + return false + } + + if iter.al.size == 0 { + return false + } + + if iter.cur >= iter.al.size-1 { + iter.cur = 0 + } else { + iter.cur++ + } + return true +} + +func (iter *CircularIterator) ToHead() { + iter.isInit = true + iter.cur = 0 +} + +func (iter *CircularIterator) ToTail() { + iter.isInit = true + iter.cur = iter.al.size - 1 +} diff --git a/list/linked_list/iterator.go b/list/linked_list/iterator.go index 2024612..013af73 100644 --- a/list/linked_list/iterator.go +++ b/list/linked_list/iterator.go @@ -78,10 +78,10 @@ func (iter *CircularIterator) Next() bool { return true } -func (iter *CircularIterator) MoveToHead() { +func (iter *CircularIterator) ToHead() { iter.cur = iter.pl.head } -func (iter *CircularIterator) MoveToTail() { +func (iter *CircularIterator) ToTail() { iter.cur = iter.pl.tail } diff --git a/list/linked_list/linked_list.go b/list/linked_list/linked_list.go index dea0ad0..6c1003d 100644 --- a/list/linked_list/linked_list.go +++ b/list/linked_list/linked_list.go @@ -3,6 +3,7 @@ package linkedlist import ( "fmt" + "github.com/474420502/focus/list" "github.com/davecgh/go-spew/spew" ) @@ -22,6 +23,11 @@ type LinkedList struct { size uint } +func assertImplementation() { + var _ list.IList = (*LinkedList)(nil) + var _ list.ILinkedList = (*LinkedList)(nil) +} + func New() *LinkedList { l := &LinkedList{} l.head = &Node{} @@ -44,8 +50,10 @@ func (l *LinkedList) CircularIterator() *CircularIterator { } func (l *LinkedList) Clear() { - l.head.next = nil - l.tail.prev = nil + + l.head.next = l.tail + l.tail.prev = l.head + l.size = 0 } @@ -57,6 +65,21 @@ func (l *LinkedList) Size() uint { return l.size } +func (l *LinkedList) Push(value interface{}) { + var node *Node + l.size++ + + node = &Node{} + node.value = value + + tprev := l.tail.prev + tprev.next = node + + node.prev = tprev + node.next = l.tail + l.tail.prev = node +} + func (l *LinkedList) PushFront(values ...interface{}) { var node *Node @@ -433,6 +456,24 @@ TOPFOR: return } +func (l *LinkedList) Contains(values ...interface{}) bool { + + for _, searchValue := range values { + found := false + for cur := l.head.next; cur != l.tail; cur = cur.next { + if cur.value == searchValue { + found = true + break + } + } + + if !found { + return false + } + } + return true +} + func (l *LinkedList) Values() (result []interface{}) { l.Traversal(func(value interface{}) bool { result = append(result, value) diff --git a/list/linked_list/linked_list_test.go b/list/linked_list/linked_list_test.go index 84eb948..0ee5043 100644 --- a/list/linked_list/linked_list_test.go +++ b/list/linked_list/linked_list_test.go @@ -3,10 +3,27 @@ package linkedlist import ( "testing" - "github.com/Pallinder/go-randomdata" "github.com/davecgh/go-spew/spew" ) +func TestPush(t *testing.T) { + l := New() + for i := 0; i < 5; i++ { + l.Push(i) + } + var result string + result = spew.Sprint(l.Values()) + if result != "[0 1 2 3 4]" { + t.Error(result) + } + + l.Push(0) + result = spew.Sprint(l.Values()) + if result != "[0 1 2 3 4 0]" { + t.Error(result) + } +} + func TestPushFront(t *testing.T) { l := New() for i := 0; i < 5; i++ { @@ -552,6 +569,35 @@ func TestRemoveIf2(t *testing.T) { } } +func TestTraversal(t *testing.T) { + l := New() + for i := 0; i < 5; i++ { + l.PushFront(uint(i)) + } + + var result []interface{} + + l.Traversal(func(v interface{}) bool { + result = append(result, v) + return true + }) + + if spew.Sprint(result) != "[4 3 2 1 0]" { + t.Error(result) + } + + l.PushBack(7, 8) + result = nil + l.Traversal(func(v interface{}) bool { + result = append(result, v) + return true + }) + + if spew.Sprint(result) != "[4 3 2 1 0 7 8]" { + t.Error(result) + } +} + func TestIterator(t *testing.T) { ll := New() for i := 0; i < 10; i++ { @@ -602,7 +648,7 @@ func TestCircularIterator(t *testing.T) { } } - iter.MoveToTail() + iter.ToTail() for i := 0; i != 10; i++ { iter.Prev() if iter.Value() != i { @@ -621,46 +667,82 @@ func TestCircularIterator(t *testing.T) { } } -func BenchmarkPushBack(b *testing.B) { - - ec := 5 - cs := 2000000 - b.N = cs * ec - - for c := 0; c < ec; c++ { - l := New() - for i := 0; i < cs; i++ { - l.PushBack(i) - } +func TestContains(t *testing.T) { + ll := New() + for i := 0; i < 10; i++ { + ll.Push(i) } -} -func BenchmarkPushFront(b *testing.B) { - - ec := 5 - cs := 2000000 - b.N = cs * ec - - for c := 0; c < ec; c++ { - l := New() - for i := 0; i < cs; i++ { - l.PushFront(i) + for i := 0; i < 10; i++ { + if !ll.Contains(i) { + t.Error(i) } } -} - -func BenchmarkInsert(b *testing.B) { - - ec := 10 - cs := 1000 - b.N = cs * ec - - for c := 0; c < ec; c++ { - l := New() - for i := 0; i < cs; i++ { - ridx := randomdata.Number(0, int(l.Size())+1) - l.Insert(uint(ridx), i) + for i := 10; i < 20; i++ { + if ll.Contains(i) { + t.Error(i) } } + + if v, _ := ll.Front(); v != 0 { + t.Error(v) + } + + if v, _ := ll.Back(); v != 9 { + t.Error(v) + } + + ll.Clear() + if !ll.Empty() { + t.Error("not Empty?") + } + + if v, ok := ll.Front(); ok { + t.Error(v) + } } + +// func BenchmarkPushBack(b *testing.B) { + +// ec := 5 +// cs := 2000000 +// b.N = cs * ec + +// for c := 0; c < ec; c++ { +// l := New() +// for i := 0; i < cs; i++ { +// l.PushBack(i) +// } +// } +// } + +// func BenchmarkPushFront(b *testing.B) { + +// ec := 5 +// cs := 2000000 +// b.N = cs * ec + +// for c := 0; c < ec; c++ { +// l := New() +// for i := 0; i < cs; i++ { +// l.PushFront(i) +// } +// } + +// } + +// func BenchmarkInsert(b *testing.B) { + +// ec := 10 +// cs := 1000 +// b.N = cs * ec + +// for c := 0; c < ec; c++ { +// l := New() +// for i := 0; i < cs; i++ { +// ridx := randomdata.Number(0, int(l.Size())+1) +// l.Insert(uint(ridx), i) +// } +// } +// } diff --git a/list/list.go b/list/list.go new file mode 100644 index 0000000..b53fe6e --- /dev/null +++ b/list/list.go @@ -0,0 +1,23 @@ +package list + +// IList 通用接口 +type IList interface { + Push(value interface{}) + Contains(values ...interface{}) bool + Index(idx uint) (interface{}, bool) + Remove(idx uint) (result interface{}, isfound bool) + Values() []interface{} + Traversal(every func(interface{}) bool) + + Clear() + Empty() bool + Size() uint +} + +// ILinkedList 通用接口 +type ILinkedList interface { + PushFront(values ...interface{}) + PushBack(values ...interface{}) + PopFront() (result interface{}, found bool) + PopBack() (result interface{}, found bool) +} diff --git a/list/priority_list/priority_list.go b/list/priority_list/priority_list.go index bb5897b..8e0128b 100644 --- a/list/priority_list/priority_list.go +++ b/list/priority_list/priority_list.go @@ -14,10 +14,15 @@ type Node struct { type PriorityList struct { head, tail *Node - size int + size uint Compare compare.Compare } +// 优先队列的Index 正负都有作用要定义一种新的接口类型 +func assertImplementation() { + // var _ list.IList = (*PriorityList)(nil) +} + func New(Compare compare.Compare) *PriorityList { pl := &PriorityList{head: &Node{}, tail: &Node{}, size: 0, Compare: Compare} pl.head.next = pl.tail @@ -57,10 +62,20 @@ func (pl *PriorityList) CircularIterator() *CircularIterator { return &CircularIterator{pl: pl, cur: pl.head} } -func (pl *PriorityList) Size() int { +func (pl *PriorityList) Size() uint { return pl.size } +func (pl *PriorityList) Empty() bool { + return pl.size == 0 +} + +func (pl *PriorityList) Clear() { + pl.head.next = pl.tail + pl.tail.prev = pl.head + pl.size = 0 +} + func (pl *PriorityList) Push(value interface{}) { pl.size++ pnode := &Node{value: value} @@ -110,13 +125,31 @@ func (pl *PriorityList) Pop() (result interface{}, ok bool) { return nil, false } -func (pl *PriorityList) Get(idx int) (interface{}, bool) { +func (pl *PriorityList) Index(idx int) (interface{}, bool) { if n, ok := pl.GetNode(idx); ok { return n.value, true } return nil, false } +func (l *PriorityList) Contains(values ...interface{}) bool { + + for _, searchValue := range values { + found := false + for cur := l.head.next; cur != l.tail; cur = cur.next { + if cur.value == searchValue { + found = true + break + } + } + + if !found { + return false + } + } + return true +} + func (pl *PriorityList) GetNode(idx int) (*Node, bool) { if idx >= 0 { cur := pl.head.next @@ -163,3 +196,11 @@ func (pl *PriorityList) Values() []interface{} { } return values } + +func (l *PriorityList) Traversal(every func(interface{}) bool) { + for cur := l.head.next; cur != l.tail; cur = cur.next { + if !every(cur.value) { + break + } + } +} diff --git a/list/priority_list/priority_list_test.go b/list/priority_list/priority_list_test.go index 4c5d0e9..74ffa5f 100644 --- a/list/priority_list/priority_list_test.go +++ b/list/priority_list/priority_list_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/474420502/focus/compare" + "github.com/davecgh/go-spew/spew" ) func loadTestData() []int { @@ -128,14 +129,14 @@ func TestGet(t *testing.T) { } for _, v := range []int{0, 9, 5, 7} { - if g, ok := pl.Get(v); ok { + if g, ok := pl.Index(v); ok { if g != (9 - v) { t.Error(v, "Get == ", g) } } } - if n, ok := pl.Get(10); ok { + if n, ok := pl.Index(10); ok { t.Error("index 10 is over size", n) } } @@ -207,14 +208,14 @@ func TestRemove(t *testing.T) { } pl.RemoveWithIndex(0) - if g, ok := pl.Get(0); ok { + if g, ok := pl.Index(0); ok { if g != 8 { t.Error(g) } } pl.RemoveWithIndex(-1) - if g, ok := pl.Get(-1); ok { + if g, ok := pl.Index(-1); ok { if g != 1 { t.Error(g) } @@ -222,6 +223,60 @@ func TestRemove(t *testing.T) { } +func TestTraversal(t *testing.T) { + l := New(compare.Int) + for i := 0; i < 5; i++ { + l.Push(i) + } + + var result []interface{} + + l.Traversal(func(v interface{}) bool { + result = append(result, v) + return true + }) + + if spew.Sprint(result) != "[4 3 2 1 0]" { + t.Error(result) + } + + l.Push(7) + l.Push(6) + result = nil + l.Traversal(func(v interface{}) bool { + result = append(result, v) + return true + }) + + if spew.Sprint(result) != "[7 6 4 3 2 1 0]" { + t.Error(result) + } +} + +func TestContains(t *testing.T) { + ll := New(compare.Int) + for i := 0; i < 10; i++ { + ll.Push(i) + } + + for i := 0; i < 10; i++ { + if !ll.Contains(i) { + t.Error(i) + } + } + + for i := 10; i < 20; i++ { + if ll.Contains(i) { + t.Error(i) + } + } + + if spew.Sprint(ll.Values()) != "[9 8 7 6 5 4 3 2 1 0]" { + t.Error(spew.Sprint(ll.Values())) + } + +} + // func BenchmarkGet(b *testing.B) { // pl := New(compare.Int)