From 5483380066c6d399c8a9e021117a91dfa1567d37 Mon Sep 17 00:00:00 2001 From: dudaodong Date: Fri, 8 Apr 2022 17:39:54 +0800 Subject: [PATCH] refactor: rewrite arrayqueue --- datastructure/queue/arrayqueue.go | 84 ++++++++++++++++---------- datastructure/queue/arrayqueue_test.go | 52 ++++++++++------ 2 files changed, 85 insertions(+), 51 deletions(-) diff --git a/datastructure/queue/arrayqueue.go b/datastructure/queue/arrayqueue.go index 28db4d1..a2dfd2b 100644 --- a/datastructure/queue/arrayqueue.go +++ b/datastructure/queue/arrayqueue.go @@ -1,79 +1,101 @@ package datastructure import ( - "errors" "fmt" "reflect" ) // ArrayQueue implements queue with slice type ArrayQueue[T any] struct { - data []T - length int + items []T + head int + tail int + capacity int + size int } -// NewArrayQueue return a empty ArrayQueue pointer -func NewArrayQueue[T any](values ...T) *ArrayQueue[T] { - data := make([]T, len(values)) - for i, v := range values { - data[i] = v +func NewArrayQueue[T any](capacity int) *ArrayQueue[T] { + return &ArrayQueue[T]{ + items: make([]T, 0, capacity), + head: 0, + tail: 0, + capacity: capacity, + size: 0, } - return &ArrayQueue[T]{data: data, length: len(values)} } // Data return queue data func (q *ArrayQueue[T]) Data() []T { - return q.data + items := []T{} + for i := q.head; i < q.tail; i++ { + items = append(items, q.items[i]) + } + return items } // Size return length of queue data func (q *ArrayQueue[T]) Size() int { - return q.length + return q.size } // IsEmpty checks if queue is empty or not func (q *ArrayQueue[T]) IsEmpty() bool { - return q.length == 0 + return q.size == 0 } // Front return front value of queue func (q *ArrayQueue[T]) Front() T { - return q.data[0] + return q.items[0] } // Back return back value of queue func (q *ArrayQueue[T]) Back() T { - return q.data[q.length-1] + return q.items[q.size-1] } // EnQueue put element into queue -func (q *ArrayQueue[T]) EnQueue(value T) { - q.data = append(q.data, value) - q.length++ +func (q *ArrayQueue[T]) Enqueue(item T) bool { + if q.head == 0 && q.tail == q.capacity { + return false + } else if q.head != 0 && q.tail == q.capacity { + for i := q.head; i < q.tail; i++ { + q.items[i-q.head] = q.items[i] + } + q.tail = q.tail - q.head + q.head = 0 + } + + q.items = append(q.items, item) + q.tail++ + q.size++ + return true } // DeQueue remove head element of queue and return it, if queue is empty, return nil and error -func (q *ArrayQueue[T]) DeQueue() (*T, error) { - if q.IsEmpty() { - return nil, errors.New("queue is empty") +func (q *ArrayQueue[T]) Dequeue() (T, bool) { + var item T + if q.head == q.tail { + return item, false } - - headItem := q.data[0] - q.data = q.data[1:] - q.length-- - - return &headItem, nil + item = q.items[q.head] + q.head++ + q.size-- + return item, true } // Clear the queue data func (q *ArrayQueue[T]) Clear() { - q.data = []T{} - q.length = 0 + capacity := q.capacity + q.items = make([]T, 0, capacity) + q.head = 0 + q.tail = 0 + q.size = 0 + q.capacity = capacity } // Contain checks if the value is in queue or not func (q *ArrayQueue[T]) Contain(value T) bool { - for _, v := range q.data { + for _, v := range q.items { if reflect.DeepEqual(v, value) { return true } @@ -84,8 +106,8 @@ func (q *ArrayQueue[T]) Contain(value T) bool { // Print queue data func (q *ArrayQueue[T]) Print() { info := "[" - for _, v := range q.data { - info += fmt.Sprintf("%+v, ", v) + for i := q.head; i < q.tail; i++ { + info += fmt.Sprintf("%+v, ", q.items[i]) } info += "]" fmt.Println(info) diff --git a/datastructure/queue/arrayqueue_test.go b/datastructure/queue/arrayqueue_test.go index aeed22e..c3c461c 100644 --- a/datastructure/queue/arrayqueue_test.go +++ b/datastructure/queue/arrayqueue_test.go @@ -6,13 +6,13 @@ import ( "github.com/duke-git/lancet/v2/internal" ) -func TestArrayQueue_EnQueue(t *testing.T) { - assert := internal.NewAssert(t, "TestArrayQueue_EnQueue") +func TestArrayQueue_Enqueue(t *testing.T) { + assert := internal.NewAssert(t, "TestArrayQueue_Enqueue") - queue := NewArrayQueue[int]() - queue.EnQueue(1) - queue.EnQueue(2) - queue.EnQueue(3) + queue := NewArrayQueue[int](5) + queue.Enqueue(1) + queue.Enqueue(2) + queue.Enqueue(3) expected := []int{1, 2, 3} data := queue.Data() @@ -24,26 +24,30 @@ func TestArrayQueue_EnQueue(t *testing.T) { assert.Equal(3, size) } -func TestArrayQueue_DeQueue(t *testing.T) { - assert := internal.NewAssert(t, "TestArrayQueue_DeQueue") +func TestArrayQueue_Dequeue(t *testing.T) { + assert := internal.NewAssert(t, "TestArrayQueue_Dequeue") - queue := NewArrayQueue(1, 2, 3) + queue := NewArrayQueue[int](4) + queue.Enqueue(1) + queue.Enqueue(2) + queue.Enqueue(3) - val, err := queue.DeQueue() - if err != nil { - t.Fail() - } + val, ok := queue.Dequeue() + assert.Equal(true, ok) queue.Print() - assert.Equal(1, *val) - + assert.Equal(1, val) assert.Equal([]int{2, 3}, queue.Data()) } func TestArrayQueue_Front(t *testing.T) { assert := internal.NewAssert(t, "TestArrayQueue_Front") - queue := NewArrayQueue(1, 2, 3) + queue := NewArrayQueue[int](4) + queue.Enqueue(1) + queue.Enqueue(2) + queue.Enqueue(3) + val := queue.Front() queue.Print() @@ -55,7 +59,11 @@ func TestArrayQueue_Front(t *testing.T) { func TestArrayQueue_Back(t *testing.T) { assert := internal.NewAssert(t, "TestArrayQueue_Back") - queue := NewArrayQueue(1, 2, 3) + queue := NewArrayQueue[int](4) + queue.Enqueue(1) + queue.Enqueue(2) + queue.Enqueue(3) + val := queue.Back() queue.Print() @@ -67,7 +75,10 @@ func TestArrayQueue_Back(t *testing.T) { func TestArrayQueue_Contain(t *testing.T) { assert := internal.NewAssert(t, "TestArrayQueue_Contain") - queue := NewArrayQueue(1, 2, 3) + queue := NewArrayQueue[int](4) + queue.Enqueue(1) + queue.Enqueue(2) + queue.Enqueue(3) assert.Equal(true, queue.Contain(1)) assert.Equal(false, queue.Contain(4)) @@ -76,11 +87,12 @@ func TestArrayQueue_Contain(t *testing.T) { func TestArrayQueue_Clear(t *testing.T) { assert := internal.NewAssert(t, "TestArrayQueue_Clear") - queue := NewArrayQueue[int]() + queue := NewArrayQueue[int](4) + assert.Equal(true, queue.IsEmpty()) assert.Equal(0, queue.Size()) - queue.EnQueue(1) + queue.Enqueue(1) assert.Equal(false, queue.IsEmpty()) assert.Equal(1, queue.Size())