队列(Queue)
- 队列是一个有序列表,可以用数组或链表实现
- 遵循先入先出原则
数组模拟队列
- 队列本身是有序数列,若使用数组的结构来存储队列的数据,则队列数组的声明如下 其中maxSize是该队列的最大容量
- 队列的输入、输出是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随数据输出而改变,而rear则是随数据的输入而改变
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-irWHTpRV-1611058357382)(https://i.loli.net/2021/01/17/RJIKUMdmjDp8uck.png)]
- addqueue处理步骤:
- 将尾指针后移:rear+1,front==rear(空)
- 若尾指针rear小于等于队列的最大下标Maxsize-1,则将数据存入rear所指的数组元素中,否则无法存入数据。rear==Maxsize-1(队满)
package main
import (
"errors"
"fmt"
"os"
)
//使用结构体管理队列
type Queue struct {
maxSize int
front int
rear int
array []int
}
//队列初始化
func (this *Queue) initQue(n int) {
this.maxSize = n
this.array = make([]int, n)
this.front = -1
this.rear = -1
return
}
//添加数据到队列
func (this *Queue) AddQueue(val int) (err error) {
//先判断队列是否已满
if this.rear == (this.maxSize-1) {
return errors.New("queue full")
}
this.rear++
this.array[this.rear] = val
return
}
//从队列中取出数据,不包含front
func (this *Queue) GetQueue()(val int,err error){
//判断队列是否为空
if this.front==this.rear{
return -1,errors.New("queue empty")
}
this.front++
val = this.array[this.front]
return val,err
}
//显示队列,找到队首,然后遍历到队尾,不包含队首的元素
func (this *Queue) ShowQueue() {
fmt.Println("队列当前的情况是:")
for i := this.front + 1; i <= this.rear; i++ {
fmt.Printf("array[%d]=%d\t\n", i, this.array[i])
}
}
func main() {
var queue Queue
queue.initQue(4)
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.AddQueue(val)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("加入队列ok")
}
case "get":
val,err :=queue.GetQueue()
if err !=nil{
fmt.Println(err.Error())
}else{
fmt.Println(val)
}
case "show":
queue.ShowQueue()
case "exit":
os.Exit(0)
}
}
}
缺点及优化:
缺点:分析可得,向队列插入元素至队满后,即使出队列,rear的值仍为栈顶,不能有新元素入栈,造成浪费
优化:环形队列,将数组看成环形的(取模实现)
- 尾索引的下一个为头索引时为满
- 尾索引==头索引时为空
//使用结构体管理一个环形队列
type CircleQueue struct {
maxSize int
array [5]int
head int //指向队列队首
tail int //指向队尾
}
//入队列
func (this *CircleQueue) AddQueue(val int) (err error) {
if this.IsFull() {
return errors.New("queue full")
}
//this.tail在队列尾部,但不包含最后一个元素
this.array[this.tail] = val
this.tail = (this.tail + 1) % this.maxSize
return
}
func (this *CircleQueue) GetQueue() (val int, err error) {
if this.IsEmpty() {
return 0, errors.New("queue Empty")
}
//取出,head只想队首,并且含队首元素
val = this.array[this.head]
this.head = (this.head + 1) % this.maxSize
return
}
//显示队列
func (this *CircleQueue) ShowQueue() {
size := this.Size()
if size == 0 {
fmt.Println("队列为空")
}
//设计一个辅助变量,指向head
tempHead := this.head
for i := 0; i < size; i++ {
fmt.Printf("array[%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 {
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.AddQueue(val)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("加入队列ok")
}
case "get":
val, err := queue.GetQueue()
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println(val)
}
case "show":
queue.ShowQueue()
case "exit":
os.Exit(0)
}
}
}