1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-15 18:22:27 +08:00

refactor: rewrite arrayqueue

This commit is contained in:
dudaodong
2022-04-08 17:39:54 +08:00
parent 20b9e5353e
commit 5483380066
2 changed files with 85 additions and 51 deletions

View File

@@ -1,79 +1,101 @@
package datastructure package datastructure
import ( import (
"errors"
"fmt" "fmt"
"reflect" "reflect"
) )
// ArrayQueue implements queue with slice // ArrayQueue implements queue with slice
type ArrayQueue[T any] struct { type ArrayQueue[T any] struct {
data []T items []T
length int head int
tail int
capacity int
size int
} }
// NewArrayQueue return a empty ArrayQueue pointer func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
func NewArrayQueue[T any](values ...T) *ArrayQueue[T] { return &ArrayQueue[T]{
data := make([]T, len(values)) items: make([]T, 0, capacity),
for i, v := range values { head: 0,
data[i] = v tail: 0,
capacity: capacity,
size: 0,
} }
return &ArrayQueue[T]{data: data, length: len(values)}
} }
// Data return queue data // Data return queue data
func (q *ArrayQueue[T]) Data() []T { 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 // Size return length of queue data
func (q *ArrayQueue[T]) Size() int { func (q *ArrayQueue[T]) Size() int {
return q.length return q.size
} }
// IsEmpty checks if queue is empty or not // IsEmpty checks if queue is empty or not
func (q *ArrayQueue[T]) IsEmpty() bool { func (q *ArrayQueue[T]) IsEmpty() bool {
return q.length == 0 return q.size == 0
} }
// Front return front value of queue // Front return front value of queue
func (q *ArrayQueue[T]) Front() T { func (q *ArrayQueue[T]) Front() T {
return q.data[0] return q.items[0]
} }
// Back return back value of queue // Back return back value of queue
func (q *ArrayQueue[T]) Back() T { func (q *ArrayQueue[T]) Back() T {
return q.data[q.length-1] return q.items[q.size-1]
} }
// EnQueue put element into queue // EnQueue put element into queue
func (q *ArrayQueue[T]) EnQueue(value T) { func (q *ArrayQueue[T]) Enqueue(item T) bool {
q.data = append(q.data, value) if q.head == 0 && q.tail == q.capacity {
q.length++ 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 // DeQueue remove head element of queue and return it, if queue is empty, return nil and error
func (q *ArrayQueue[T]) DeQueue() (*T, error) { func (q *ArrayQueue[T]) Dequeue() (T, bool) {
if q.IsEmpty() { var item T
return nil, errors.New("queue is empty") if q.head == q.tail {
return item, false
} }
item = q.items[q.head]
headItem := q.data[0] q.head++
q.data = q.data[1:] q.size--
q.length-- return item, true
return &headItem, nil
} }
// Clear the queue data // Clear the queue data
func (q *ArrayQueue[T]) Clear() { func (q *ArrayQueue[T]) Clear() {
q.data = []T{} capacity := q.capacity
q.length = 0 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 // Contain checks if the value is in queue or not
func (q *ArrayQueue[T]) Contain(value T) bool { func (q *ArrayQueue[T]) Contain(value T) bool {
for _, v := range q.data { for _, v := range q.items {
if reflect.DeepEqual(v, value) { if reflect.DeepEqual(v, value) {
return true return true
} }
@@ -84,8 +106,8 @@ func (q *ArrayQueue[T]) Contain(value T) bool {
// Print queue data // Print queue data
func (q *ArrayQueue[T]) Print() { func (q *ArrayQueue[T]) Print() {
info := "[" info := "["
for _, v := range q.data { for i := q.head; i < q.tail; i++ {
info += fmt.Sprintf("%+v, ", v) info += fmt.Sprintf("%+v, ", q.items[i])
} }
info += "]" info += "]"
fmt.Println(info) fmt.Println(info)

View File

@@ -6,13 +6,13 @@ import (
"github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestArrayQueue_EnQueue(t *testing.T) { func TestArrayQueue_Enqueue(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_EnQueue") assert := internal.NewAssert(t, "TestArrayQueue_Enqueue")
queue := NewArrayQueue[int]() queue := NewArrayQueue[int](5)
queue.EnQueue(1) queue.Enqueue(1)
queue.EnQueue(2) queue.Enqueue(2)
queue.EnQueue(3) queue.Enqueue(3)
expected := []int{1, 2, 3} expected := []int{1, 2, 3}
data := queue.Data() data := queue.Data()
@@ -24,26 +24,30 @@ func TestArrayQueue_EnQueue(t *testing.T) {
assert.Equal(3, size) assert.Equal(3, size)
} }
func TestArrayQueue_DeQueue(t *testing.T) { func TestArrayQueue_Dequeue(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_DeQueue") 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() val, ok := queue.Dequeue()
if err != nil { assert.Equal(true, ok)
t.Fail()
}
queue.Print() queue.Print()
assert.Equal(1, *val) assert.Equal(1, val)
assert.Equal([]int{2, 3}, queue.Data()) assert.Equal([]int{2, 3}, queue.Data())
} }
func TestArrayQueue_Front(t *testing.T) { func TestArrayQueue_Front(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Front") 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() val := queue.Front()
queue.Print() queue.Print()
@@ -55,7 +59,11 @@ func TestArrayQueue_Front(t *testing.T) {
func TestArrayQueue_Back(t *testing.T) { func TestArrayQueue_Back(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Back") 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() val := queue.Back()
queue.Print() queue.Print()
@@ -67,7 +75,10 @@ func TestArrayQueue_Back(t *testing.T) {
func TestArrayQueue_Contain(t *testing.T) { func TestArrayQueue_Contain(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Contain") 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(true, queue.Contain(1))
assert.Equal(false, queue.Contain(4)) assert.Equal(false, queue.Contain(4))
@@ -76,11 +87,12 @@ func TestArrayQueue_Contain(t *testing.T) {
func TestArrayQueue_Clear(t *testing.T) { func TestArrayQueue_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Clear") assert := internal.NewAssert(t, "TestArrayQueue_Clear")
queue := NewArrayQueue[int]() queue := NewArrayQueue[int](4)
assert.Equal(true, queue.IsEmpty()) assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Size()) assert.Equal(0, queue.Size())
queue.EnQueue(1) queue.Enqueue(1)
assert.Equal(false, queue.IsEmpty()) assert.Equal(false, queue.IsEmpty())
assert.Equal(1, queue.Size()) assert.Equal(1, queue.Size())