今天来教大家如何用Go实现一个队列和一个循环队列
一、普通队列
首先,我们需要知道队列的特点是什么,那就是:先进先出
知道了这个特点之后,就可以进行代码的实现了,其实和上几期的数组,栈实现的差不多,唯一的区别在于 放入元素和取出元素的方式不同
1. 代码实现
话不多说,上代码:
package queue
type MyQueue[T any] interface {
Size() int
Front() T
End() T
IsEmpty() bool
EnQueue(T)
DeQueue() T
Clear()
}
type Queue[T any] struct {
dataStore []T
theSize int
}
func NewQueue[T any]() MyQueue[T] {
return &Queue[T]{
theSize: 0,
dataStore: make([]T, 0),
}
}
func (q *Queue[T]) Size() int {
return q.theSize
}
// Front 第一个元素
func (q *Queue[T]) Front() T {
if q.theSize == 0 {
var zero T
return zero
}
return q.dataStore[0]
}
// End 最后一个元素
func (q *Queue[T]) End() T {
if q.theSize == 0 {
var zero T
return zero
}
return q.dataStore[q.theSize-1]
}
func (q *Queue[T]) IsEmpty() bool {
return q.theSize == 0
}
func (q *Queue[T]) EnQueue(data T) {
q.dataStore = append(q.dataStore, data)
q.theSize++
}
func (q *Queue[T]) DeQueue() T {
if q.theSize == 0 {
var zero T
return zero
}
last := q.dataStore[0]
if q.theSize > 0 {
q.dataStore = q.dataStore[1:q.theSize]
} else {
q.dataStore = make([]T, 0)
}
q.theSize--
return last
}
func (q *Queue[T]) Clear() {
q.dataStore = make([]T, 0)
q.theSize = 0
}
相信应该没什么问题,无非是方法的定义可能会有些许区别。
二、循环队列(环形队列)
环形队列的要点在于,他是一个圆,我们需要两个类似指针的东西,来指示我现在的队列里面有多少元素,以及判断空与满的状态
其次,环形队列的实际大小会少一个,因为两个用来指示的 front 和 rear,当它们相等的时候,就为空,而满的状态,我们需要留出一个空间才能实现判断,rear + 1 = front 的时候,就是满。
所以,当我们不断加入元素,rear 就会不断增加,直到满。当我们不断取出元素,front 就会从 0 开始 不断增加,因为队列的特点是先进先出。
1. 代码实现
package circleQueue
import "errors"
// QueueSize 实际大小只有99个,因为需要留出一个用来表示满状态
const QueueSize = 100
// CircleQueue 环形队列,也叫循环队列
type CircleQueue[T any] struct {
data [QueueSize]T
front int // 头部
rear int // 尾部
}
func initQueue[T any](q *CircleQueue[T]) {
// 环形时 头尾重合表示空
q.front = 0
q.rear = 0
}
// QueueLength 计算长度
func QueueLength[T any](q *CircleQueue[T]) int {
// 这么做是为了防止当 front > rear的时候,会出现负数
return (q.rear - q.front + QueueSize) % QueueSize
}
// EnQueue 入队
func EnQueue[T any](q *CircleQueue[T], data T) error {
if (q.rear+1)%QueueSize == q.front%QueueSize {
return errors.New("队列已满")
}
q.data[q.rear] = data
q.rear = (q.rear + 1) % QueueSize
return nil
}
// DeQueue 出队
func DeQueue[T any](q *CircleQueue[T]) (T, error) {
var zero T
if q.front == q.rear {
return zero, errors.New("队列为空")
}
res := q.data[q.front]
q.data[q.front] = zero
q.front = (q.front + QueueSize) % QueueSize
return res, nil
}