mirror of
https://github.com/duke-git/lancet.git
synced 2025-09-27 03:45:58 +08:00
156 lines
2.9 KiB
Go
156 lines
2.9 KiB
Go
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
|
// Use of this source code is governed by MIT license
|
|
|
|
// Package datastructure contains some data structure.
|
|
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
|
|
package datastructure
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
// ArrayQueue implements queue with slice
|
|
type ArrayQueue[T any] struct {
|
|
data []T
|
|
head int
|
|
tail int
|
|
capacity int
|
|
size int
|
|
}
|
|
|
|
func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
|
|
return &ArrayQueue[T]{
|
|
data: make([]T, 0, capacity),
|
|
head: 0,
|
|
tail: 0,
|
|
capacity: capacity,
|
|
size: 0,
|
|
}
|
|
}
|
|
|
|
// Data return slice of queue data
|
|
func (q *ArrayQueue[T]) Data() []T {
|
|
items := make([]T, 0, q.tail-q.head)
|
|
for i := q.head; i < q.tail; i++ {
|
|
items = append(items, q.data[i])
|
|
}
|
|
return items
|
|
}
|
|
|
|
// Size return number of elements in queue
|
|
func (q *ArrayQueue[T]) Size() int {
|
|
return q.size
|
|
}
|
|
|
|
// IsEmpty checks if queue is empty or not
|
|
func (q *ArrayQueue[T]) IsEmpty() bool {
|
|
return q.size == 0
|
|
}
|
|
|
|
// IsFull checks if queue is full or not
|
|
func (q *ArrayQueue[T]) IsFull() bool {
|
|
return q.size == q.capacity
|
|
}
|
|
|
|
// Front return front value of queue
|
|
func (q *ArrayQueue[T]) Front() T {
|
|
return q.data[q.head]
|
|
}
|
|
|
|
// Back return back value of queue
|
|
func (q *ArrayQueue[T]) Back() T {
|
|
return q.data[q.tail-1]
|
|
}
|
|
|
|
// EnQueue put element into queue
|
|
func (q *ArrayQueue[T]) Enqueue(item T) bool {
|
|
if q.tail < q.capacity {
|
|
q.data = append(q.data, item)
|
|
// q.tail++
|
|
q.data[q.tail] = item
|
|
} else {
|
|
//upgrade
|
|
if q.head > 0 {
|
|
for i := 0; i < q.tail-q.head; i++ {
|
|
q.data[i] = q.data[i+q.head]
|
|
}
|
|
q.tail -= q.head
|
|
q.head = 0
|
|
} else {
|
|
if q.capacity < 65536 {
|
|
if q.capacity == 0 {
|
|
q.capacity = 1
|
|
}
|
|
q.capacity *= 2
|
|
} else {
|
|
q.capacity += 2 ^ 16
|
|
}
|
|
|
|
tmp := make([]T, q.capacity, q.capacity)
|
|
copy(tmp, q.data)
|
|
q.data = tmp
|
|
}
|
|
|
|
q.data[q.tail] = 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, bool) {
|
|
var item T
|
|
if q.size == 0 {
|
|
return item, false
|
|
}
|
|
|
|
item = q.data[q.head]
|
|
q.head++
|
|
|
|
if q.head >= 1024 || q.head*2 > q.tail {
|
|
q.capacity -= q.head
|
|
q.tail -= q.head
|
|
tmp := make([]T, q.capacity, q.capacity)
|
|
copy(tmp, q.data[q.head:])
|
|
q.data = tmp
|
|
q.head = 0
|
|
}
|
|
|
|
q.size--
|
|
return item, true
|
|
}
|
|
|
|
// Clear the queue data
|
|
func (q *ArrayQueue[T]) Clear() {
|
|
capacity := q.capacity
|
|
q.data = 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 {
|
|
if reflect.DeepEqual(v, value) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Print queue data
|
|
func (q *ArrayQueue[T]) Print() {
|
|
info := "["
|
|
for i := q.head; i < q.tail; i++ {
|
|
info += fmt.Sprintf("%+v, ", q.data[i])
|
|
}
|
|
info += "]"
|
|
fmt.Println(info)
|
|
}
|