思路:
-
将数组看成是一个环形的(通过取模的方式来实现)
-
什么时候表示队列满 (tail+1)%maxSize==head
-
当tail==head时表示队列为空
-
初始化时,tail=0,head=0
-
统计该队列有多少个元素 (tail+maxSize-head)%maxSize
-
tail在队列尾部,不包含最后的元素(见下面的‘注意’),head指向队首并且含队首元素
**注意:**尾索引的下一个为头索引时,表示队列满,所以要将队列容量空出一个作为约定,即在判断队列是否满的时候是(tail+1)%maxSize==head(满)
代码如下:
package main
import (
"errors"
"fmt"
"os"
)
//使用一个结构体管理环形队列
type circleQueue struct {
maxSize int //
array [5]int //数组
head int //指向队列队首
tail int //指向队列队尾
}
//入队列
func (this *circleQueue) push(val int) (err error) {
if this.isFull() {
return errors.New("队列满了")
}
//this.tail在队列尾部,但是不包含最后的元素
this.array[this.tail] = val
this.tail = (this.tail + 1) % this.maxSize
return
}
//出队列
func (this *circleQueue) pop() (val int, err error) {
if this.isEmpty() {
return 0, errors.New("队列是空的")
}
//取出,head指向队首并且含队首元素
this.head = (this.head + 1) % this.maxSize
return
}
//显示队列
func (this *circleQueue) listQueue() {
fmt.Println("环形队列情况如下")
//取出当前队列有多少个元素
size := this.size()
if size == 0 {
fmt.Println("队列为空")
}
//设计一个辅助变量,指向head
tempHead := this.head
for i := 0; i < size; i++ {
fmt.Printf("arr[%d]=%d\t", tempHead, this.array[tempHead])
tempHead = (tempHead + 1) % this.maxSize
}
fmt.Println()
}
//判断环形队列为满
func (this *circleQueue) isFull() bool {
return (this.tail+1)%this.maxSize == this.head
}
//判断队列是否为空
func (this *circleQueue) isEmpty() bool {
return this.tail == this.head
}
//环形队列有多少个元素
func (this *circleQueue) size() int {
//重要:一定要看
//环形队列,head在不停的增长,快出去的时候加了一个maxSize,又拐回来,所以tail
//某个情况下,自然值是小于head的,因此tail需要+maxSize再-head,然后再对maxSize取模
return (this.tail + this.maxSize - this.head) % this.maxSize
}
func main() {
//初始化环形队列
queue := &circleQueue{
maxSize: 5,
head: 0,
tail: 0,
}
var key string
var val int
for {
fmt.Println("1.输入add 表示添加数据到队列")
fmt.Println("2.输入get 表示从队列获取数据")
fmt.Println("3.输入show 表示显示队列")
fmt.Println("4.输入exit 表示结束队列")
fmt.Scanln(&key)
switch key {
case "add":
fmt.Println("输入你要输入的队列数")
fmt.Scanln(&val)
err := queue.push(val)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("加入队列OK")
}
case "get":
val, err := queue.pop()
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("从队列中取出了", val)
}
fmt.Println("get")
case "show":
queue.listQueue()
case "exit":
os.Exit(0)
}
}
}