做的就是利用循环来解决空间浪费的问题
package main
import (
"errors"
"fmt"
"strconv"
)
// 循环队列实现方法
type loopQueue struct {
queues []interface{}
front int //队首
tail int //队尾
length int //队伍长度
capacity int //队伍容量
}
// 创建循环队列,可指定容量,默认为0
func NewLoopQueue(args ...int) *loopQueue {
var capacity int
if len(args) == 1 {
capacity = args[0]
} else if len(args) > 1 {
panic("params invalid")
}
loop := &loopQueue{
queues: make([]interface{}, 0, capacity),
}
//初始化队列
for i := 0; i < capacity; i++ {
loop.queues = append(loop.queues, "")
}
return loop
}
func (q *loopQueue) Len() int {
return q.length
}
func (q *loopQueue) Cap() int {
return q.capacity
}
func (q *loopQueue) IsEmpty() bool {
return q.length == 0
}
func (q *loopQueue) IsFull() bool {
return (q.length + 1) >= q.capacity
}
func (q *loopQueue) GetFront() (interface{}, error) {
if q.Len() == 0 {
return nil, errors.New(
"failed to getFront,queues is empty.")
}
return q.queues[q.front], nil
}
// 向队尾增加元素
func (q *loopQueue) Enqueue(elem interface{}) {
// 队列扩容
if q.IsFull() {
buffer := new(loopQueue)
//初始化队列
bufCap := 2 * q.capacity
if bufCap == 0 {
bufCap = 1
}
for i := 0; i < bufCap; i++ {
buffer.queues = append(buffer.queues, "")
}
for i := 0; i < q.length; i++ {
buffer.queues[i] = q.queues[q.front]
q.front = (q.front + 1) % q.capacity
}
q.queues = buffer.queues
q.front = 0
q.tail = q.length
q.capacity = bufCap
}
q.queues[q.tail] = elem
q.tail = (q.tail + 1) % q.capacity
q.length++
}
// 从循环队列中队首取出元素
func (q *loopQueue) Dequeue() (interface{}, error) {
if q.IsEmpty() {
return nil, errors.New("failed to dequeue,queues is empty")
}
// 当队列长度小于容量1/4时,队列容量缩短一半
if q.length <= q.capacity/4 {
buffer := new(loopQueue)
//初始化队列
for i := 0; i < q.capacity/2; i++ {
buffer.queues = append(buffer.queues, "")
}
for i := 0; i < q.length; i++ {
buffer.queues[i] = q.queues[q.front]
q.front = (q.front + 1) % q.capacity
}
q.queues = buffer.queues
q.front = 0
q.tail = q.length
q.capacity = q.capacity / 2
}
value := q.queues[q.front]
q.front = (q.front + 1) % q.capacity
q.length--
return value, nil
}
// 测试队列
func main() {
q := NewLoopQueue()
for i := 0; i < 5; i++ {
q.Enqueue(fmt.Sprintln(strconv.Itoa(i)))
}
fmt.Printf("isEmpty:%v, isFull:%v, len=%v, cap=%v, getFront=%v\n",
q.IsEmpty(), q.IsFull(), q.Len(), q.Cap(), fmt.Sprintln(q.GetFront()))
fmt.Printf("isEmpty:%v, isFull:%v, len=%v, cap=%v, dequeue=%v\n",
q.IsEmpty(), q.IsFull(), q.Len(), q.Cap(), fmt.Sprintln(q.Dequeue()))
fmt.Printf("isEmpty:%v, isFull:%v, len=%v, cap=%v, dequeue=%v\n",
q.IsEmpty(), q.IsFull(), q.Len(), q.Cap(), fmt.Sprintln(q.Dequeue()))
fmt.Printf("isEmpty:%v, isFull:%v, len=%v, cap=%v, dequeue=%v\n",
q.IsEmpty(), q.IsFull(), q.Len(), q.Cap(), fmt.Sprintln(q.Dequeue()))
fmt.Printf("isEmpty:%v, isFull:%v, len=%v, cap=%v, dequeue=%v\n",
q.IsEmpty(), q.IsFull(), q.Len(), q.Cap(), fmt.Sprintln(q.Dequeue()))
fmt.Printf("isEmpty:%v, isFull:%v, len=%v, cap=%v, dequeue=%v\n",
q.IsEmpty(), q.IsFull(), q.Len(), q.Cap(), fmt.Sprintln(q.Dequeue()))
fmt.Printf("isEmpty:%v, isFull:%v, len=%v, cap=%v, dequeue=%v\n",
q.IsEmpty(), q.IsFull(), q.Len(), q.Cap(), fmt.Sprintln(q.Dequeue()))
fmt.Printf("isEmpty:%v, isFull:%v, len=%v, cap=%v, getFront=%v\n",
q.IsEmpty(), q.IsFull(), q.Len(), q.Cap(), fmt.Sprintln(q.GetFront()))
}