Skip to content

Commit 4b697de

Browse files
committed
refactor basic data structure
1 parent 38a3619 commit 4b697de

11 files changed

+253
-134
lines changed

basic/link_queue.go basic/list.go

+15-11
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,34 @@
1414

1515
package basic
1616

17-
type LinkQueue[T any] struct {
17+
type List[T any] struct {
1818
head *elem[T]
1919
tail *elem[T]
2020
size int
2121
}
2222

23-
func NewLinkQueue[T any]() *LinkQueue[T] {
24-
return new(LinkQueue[T])
23+
func NewList[T any]() *List[T] {
24+
return new(List[T])
2525
}
2626

2727
type elem[T any] struct {
2828
v T
2929
next *elem[T]
3030
}
3131

32-
func (q *LinkQueue[T]) Peek() *T {
33-
return &q.head.v
32+
func (q *List[T]) Front() T {
33+
return q.head.v
3434
}
3535

36-
func (q *LinkQueue[T]) PopFront() T {
37-
e := q.head.v
36+
func (q *List[T]) PopFront() {
37+
q.size--
3838
q.head = q.head.next
3939
if q.head == nil {
4040
q.tail = nil
4141
}
42-
q.size--
43-
return e
4442
}
4543

46-
func (q *LinkQueue[T]) PushBack(e T) {
44+
func (q *List[T]) PushBack(e T) {
4745
q.size++
4846
if q.head == nil {
4947
q.head = &elem[T]{
@@ -58,6 +56,12 @@ func (q *LinkQueue[T]) PushBack(e T) {
5856
q.tail = q.tail.next
5957
}
6058

61-
func (q *LinkQueue[T]) Size() int {
59+
func (q *List[T]) Size() int {
6260
return q.size
6361
}
62+
63+
type Fifo[T any] interface {
64+
Front() T
65+
PopFront()
66+
PushBack(v T)
67+
}

basic/queue.go

+37-21
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ type Queue[T any] struct {
2121
}
2222

2323
func NewQueue[T any](cap int) *Queue[T] {
24-
if cap < MinCap {
25-
cap = MinCap
24+
if cap < 2 {
25+
cap = 2
2626
}
2727
return &Queue[T]{
2828
elems: make([]T, cap),
@@ -32,59 +32,75 @@ func NewQueue[T any](cap int) *Queue[T] {
3232
func QueueFrom[T any](elems []T) *Queue[T] {
3333
return &Queue[T]{
3434
elems: elems[:cap(elems)],
35-
back: len(elems) - 1,
35+
back: len(elems),
3636
size: len(elems),
3737
}
3838
}
3939

40-
func (q *Queue[T]) Peek() *T {
40+
func (q *Queue[T]) Front() T {
4141
if q.size <= 0 {
42-
return nil
42+
panic("empty queue")
4343
}
44-
return &q.elems[q.head]
44+
return q.elems[q.head]
4545
}
4646

47-
func (q *Queue[T]) PopFront() T {
47+
func (q *Queue[T]) Back() T {
4848
if q.size <= 0 {
4949
panic("empty queue")
5050
}
51-
e := q.elems[q.head]
51+
back := q.back - 1
52+
if back < 0 {
53+
back = len(q.elems) - 1
54+
}
55+
return q.elems[back]
56+
}
57+
58+
func (q *Queue[T]) PopFront() {
59+
if q.size <= 0 {
60+
panic("empty queue")
61+
}
62+
q.size--
5263
q.head++
5364
if q.head == len(q.elems) {
5465
q.head = 0
5566
}
67+
}
68+
69+
func (q *Queue[T]) PopBack() {
70+
if q.size <= 0 {
71+
panic("empty queue")
72+
}
5673
q.size--
57-
return e
74+
q.back--
75+
if q.back < 0 {
76+
q.back = len(q.elems) - 1
77+
}
5878
}
5979

6080
func (q *Queue[T]) PushBack(e T) {
6181
if q.size <= 0 {
6282
q.elems[0] = e
6383
q.head = 0
64-
q.back = 0
84+
q.back = 1
6585
q.size = 1
6686
return
6787
}
68-
if q.isFull() {
88+
if q.size == len(q.elems) {
6989
expand := make([]T, 2*len(q.elems))
70-
n := q.Size()
90+
n := q.size
7191
for i := 0; i < n; i++ {
7292
expand[i] = q.elems[(q.head+i)%len(q.elems)]
7393
}
7494
q.elems = expand
7595
q.head = 0
76-
q.back = n - 1
96+
q.back = n
7797
}
98+
q.size++
99+
q.elems[q.back] = e
78100
q.back++
79101
if q.back == len(q.elems) {
80102
q.back = 0
81103
}
82-
q.elems[q.back] = e
83-
q.size++
84-
}
85-
86-
func (q *Queue[T]) isFull() bool {
87-
return q.size == len(q.elems)
88104
}
89105

90106
func (q *Queue[T]) Size() int {
@@ -93,8 +109,8 @@ func (q *Queue[T]) Size() int {
93109

94110
func (q *Queue[T]) Clone() []T {
95111
elems := make([]T, 0, q.size)
96-
for q.size > 0 {
97-
elems = append(elems, q.PopFront())
112+
for q.Size() > 0 {
113+
elems = append(elems, q.Front())
98114
}
99115
return elems
100116
}

basic/queue_test.go

+48-3
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,65 @@ func BenchmarkQueue_PopFront(b *testing.B) {
3838
}
3939

4040
func BenchmarkLinkQueue_PushBack(b *testing.B) {
41-
q := NewLinkQueue[int]()
41+
q := NewList[int]()
4242
b.ResetTimer()
4343
for i := 0; i < b.N; i++ {
4444
q.PushBack(i)
4545
}
4646
}
4747

4848
func BenchmarkLinkQueue_PopFront(b *testing.B) {
49-
q := NewLinkQueue[int]()
49+
q := NewList[int]()
5050
for i := 0; i < b.N; i++ {
5151
q.PushBack(i)
5252
}
5353
b.ResetTimer()
54-
for i := 0; i < b.N; i++ {
54+
for q.Size() > 0 {
5555
q.PopFront()
5656
}
5757
}
58+
59+
func TestQueue(t *testing.T) {
60+
var queues = [2]Fifo[int]{
61+
NewQueue[int](0),
62+
NewList[int](),
63+
}
64+
pushFn := func(v int) {
65+
for _, q := range queues {
66+
q.PushBack(v)
67+
}
68+
}
69+
popFn := func() {
70+
v := queues[0].Front()
71+
for _, q := range queues {
72+
if v != q.Front() {
73+
t.Fatal()
74+
}
75+
q.PopFront()
76+
}
77+
}
78+
for i := 0; i < 1000; i++ {
79+
pushFn(i)
80+
}
81+
for i := 0; i < 500; i++ {
82+
popFn()
83+
}
84+
for i := 0; i < 2000; i++ {
85+
pushFn(i)
86+
}
87+
for i := 0; i < 1500; i++ {
88+
popFn()
89+
}
90+
for i := 0; i < 1000; i++ {
91+
pushFn(i)
92+
}
93+
for i := 0; i < 2000; i++ {
94+
popFn()
95+
}
96+
for i := 0; i < 100; i++ {
97+
pushFn(i)
98+
}
99+
for i := 0; i < 100; i++ {
100+
popFn()
101+
}
102+
}

0 commit comments

Comments
 (0)