mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
feat: add CircularQueue
This commit is contained in:
119
datastructure/queue/circularqueue.go
Normal file
119
datastructure/queue/circularqueue.go
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
package datastructure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CircularQueue implements circular queue with slice,
|
||||||
|
// last index of CircularQueue don't contain value, so acturl capacity is size - 1
|
||||||
|
type CircularQueue[T any] struct {
|
||||||
|
data []T
|
||||||
|
front int
|
||||||
|
rear int
|
||||||
|
size int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCircularQueue return a empty CircularQueue pointer
|
||||||
|
func NewCircularQueue[T any](size int) *CircularQueue[T] {
|
||||||
|
data := make([]T, size)
|
||||||
|
return &CircularQueue[T]{data: data, front: 0, rear: 0, size: size}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data return queue data
|
||||||
|
func (q *CircularQueue[T]) Data() []T {
|
||||||
|
data := []T{}
|
||||||
|
|
||||||
|
front := q.front
|
||||||
|
rear := q.rear
|
||||||
|
if front <= rear {
|
||||||
|
return q.data[front:rear]
|
||||||
|
}
|
||||||
|
|
||||||
|
data = append(data, q.data[front:]...)
|
||||||
|
data = append(data, q.data[0:rear]...)
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length return current data length of queue
|
||||||
|
func (q *CircularQueue[T]) Length() int {
|
||||||
|
if q.size == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return (q.rear - q.front + q.size) % q.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks if queue is empty or not
|
||||||
|
func (q *CircularQueue[T]) IsEmpty() bool {
|
||||||
|
return q.front == q.rear
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFull checks if queue is full or not
|
||||||
|
func (q *CircularQueue[T]) IsFull() bool {
|
||||||
|
return (q.rear+1)%q.size == q.front
|
||||||
|
}
|
||||||
|
|
||||||
|
// Front return front value of queue
|
||||||
|
func (q *CircularQueue[T]) Front() T {
|
||||||
|
return q.data[q.front]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Back return back value of queue
|
||||||
|
func (q *CircularQueue[T]) Back() T {
|
||||||
|
if q.rear-1 >= 0 {
|
||||||
|
return q.data[q.rear-1]
|
||||||
|
}
|
||||||
|
return q.data[q.size-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnQueue put element into queue
|
||||||
|
func (q *CircularQueue[T]) EnQueue(value T) error {
|
||||||
|
if q.IsFull() {
|
||||||
|
return errors.New("queue is full!")
|
||||||
|
}
|
||||||
|
|
||||||
|
q.data[q.rear] = value
|
||||||
|
// q.data = append(q.data, value)
|
||||||
|
q.rear = (q.rear + 1) % q.size
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error
|
||||||
|
func (q *CircularQueue[T]) DeQueue() (*T, error) {
|
||||||
|
if q.IsEmpty() {
|
||||||
|
return nil, errors.New("queue is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
headItem := q.data[q.front]
|
||||||
|
var t T
|
||||||
|
q.data[q.front] = t
|
||||||
|
q.front = (q.front + 1) % q.size
|
||||||
|
|
||||||
|
return &headItem, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the queue data
|
||||||
|
func (q *CircularQueue[T]) Clear() {
|
||||||
|
q.data = []T{}
|
||||||
|
q.front = 0
|
||||||
|
q.rear = 0
|
||||||
|
q.size = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contain checks if the value is in queue or not
|
||||||
|
func (q *CircularQueue[T]) Contain(value T) bool {
|
||||||
|
for _, v := range q.data {
|
||||||
|
if reflect.DeepEqual(v, value) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print queue data
|
||||||
|
func (q *CircularQueue[T]) Print() {
|
||||||
|
fmt.Printf("%+v\n", q)
|
||||||
|
}
|
||||||
148
datastructure/queue/circularqueue_test.go
Normal file
148
datastructure/queue/circularqueue_test.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package datastructure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCircularQueue_EnQueue(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestCircularQueue_EnQueue")
|
||||||
|
|
||||||
|
queue := NewCircularQueue[int](6)
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
queue.EnQueue(4)
|
||||||
|
queue.EnQueue(5)
|
||||||
|
|
||||||
|
queue.Print()
|
||||||
|
// assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
||||||
|
assert.Equal(5, queue.Length())
|
||||||
|
|
||||||
|
err := queue.EnQueue(6)
|
||||||
|
assert.IsNotNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCircularQueue_DeQueue(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
|
||||||
|
|
||||||
|
queue := NewCircularQueue[int](6)
|
||||||
|
assert.Equal(true, queue.IsEmpty())
|
||||||
|
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
queue.EnQueue(4)
|
||||||
|
queue.EnQueue(5)
|
||||||
|
|
||||||
|
val, err := queue.DeQueue()
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
assert.Equal(1, *val)
|
||||||
|
assert.Equal(false, queue.IsFull())
|
||||||
|
|
||||||
|
val, _ = queue.DeQueue()
|
||||||
|
queue.Print()
|
||||||
|
assert.Equal(2, *val)
|
||||||
|
|
||||||
|
queue.EnQueue(6)
|
||||||
|
queue.Print()
|
||||||
|
assert.Equal(false, queue.IsFull())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCircularQueue_Front(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestCircularQueue_Front")
|
||||||
|
|
||||||
|
queue := NewCircularQueue[int](6)
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
queue.EnQueue(4)
|
||||||
|
queue.EnQueue(5)
|
||||||
|
|
||||||
|
queue.Print()
|
||||||
|
|
||||||
|
queue.DeQueue()
|
||||||
|
queue.DeQueue()
|
||||||
|
queue.EnQueue(6)
|
||||||
|
queue.EnQueue(7)
|
||||||
|
|
||||||
|
queue.Print()
|
||||||
|
|
||||||
|
val := queue.Front()
|
||||||
|
assert.Equal(3, val)
|
||||||
|
assert.Equal(5, queue.Length())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCircularQueue_Back(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestCircularQueue_Back")
|
||||||
|
|
||||||
|
queue := NewCircularQueue[int](6)
|
||||||
|
assert.Equal(true, queue.IsEmpty())
|
||||||
|
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
queue.EnQueue(4)
|
||||||
|
queue.EnQueue(5)
|
||||||
|
|
||||||
|
queue.Print()
|
||||||
|
assert.Equal(5, queue.Back())
|
||||||
|
|
||||||
|
queue.DeQueue()
|
||||||
|
queue.DeQueue()
|
||||||
|
queue.EnQueue(6)
|
||||||
|
queue.EnQueue(7)
|
||||||
|
|
||||||
|
queue.Print()
|
||||||
|
assert.Equal(7, queue.Back())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCircularQueue_Contain(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
|
||||||
|
|
||||||
|
queue := NewCircularQueue[int](2)
|
||||||
|
queue.EnQueue(1)
|
||||||
|
assert.Equal(true, queue.Contain(1))
|
||||||
|
assert.Equal(false, queue.Contain(2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCircularQueue_Clear(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestCircularQueue_Clear")
|
||||||
|
|
||||||
|
queue := NewCircularQueue[int](3)
|
||||||
|
assert.Equal(true, queue.IsEmpty())
|
||||||
|
assert.Equal(0, queue.Length())
|
||||||
|
|
||||||
|
queue.EnQueue(1)
|
||||||
|
assert.Equal(false, queue.IsEmpty())
|
||||||
|
assert.Equal(1, queue.Length())
|
||||||
|
|
||||||
|
queue.Clear()
|
||||||
|
assert.Equal(true, queue.IsEmpty())
|
||||||
|
assert.Equal(0, queue.Length())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCircularQueue_Data(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestCircularQueue_Data")
|
||||||
|
|
||||||
|
queue := NewCircularQueue[int](6)
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
queue.EnQueue(4)
|
||||||
|
queue.EnQueue(5)
|
||||||
|
|
||||||
|
queue.Print()
|
||||||
|
assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
||||||
|
|
||||||
|
queue.DeQueue()
|
||||||
|
queue.DeQueue()
|
||||||
|
queue.EnQueue(6)
|
||||||
|
queue.EnQueue(7)
|
||||||
|
|
||||||
|
queue.Print()
|
||||||
|
assert.Equal([]int{3, 4, 5, 6, 7}, queue.Data())
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user