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:
@@ -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)
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user