Go数据结构之数组队列
一:队列介绍
之前的随笔有提过简单提过队列
①:队列是一个有序的表可以通过数组和链表来表现;
②:遵循先进先出原则
二:非环形队列
①:若使用数组结构存储队列数据,则队列数组的必须声明一个最大队列容量如maxSize,因为队列的输出输入是分别从前后端来处理,因此需要两个变量来记录队列前后端的下标,如front(head)记录前端,rear(tail)记录后端;
②:示意图
③:使用细节
数据存入非环形数组队列时要有两个步骤
③-1:将尾指针往后移:rear++,当front==rear时表明队列为空
③-2:若尾指针rear小于等于队列maxSize-1,则将存入数据rear所在的数组元素中;当rear==maxSize-1时代表队列已满
④:使用举例
package main import ( "fmt" "errors" ) //定义数组队列 type QueueArr struct{ MaxSize int array [5]int front int rear int } //添加 func (this *QueueArr) AddQueue(val int) (err error){ if this.rear+1 == this.MaxSize { return errors.New("队列已满") } this.rear++ this.array[this.rear] = val return } //展示所有 func (this *QueueArr) GetQueue() (err error){ if this.rear == this.front { return errors.New("队列为空") } for i := this.front+1; i <= this.rear; i++ { fmt.Printf("队列第%d=%v\n", i+1, this.array[i]); } return } //获取一个数据 func (this *QueueArr) GetOneQueue() (val int, err error){ if this.rear == this.front { return -1, errors.New("队列为空") } this.front++ val = this.array[this.front] return val, err } func main() { //初始化队列 queueArr := &QueueArr{ MaxSize : 5, front : -1, rear : -1, } //添加三个数据到队列 err := queueArr.AddQueue(0) err = queueArr.AddQueue(1) err = queueArr.AddQueue(2) if err != nil { fmt.Println("添加数据到队列错误:", err) } //读取所有队列数据 err = queueArr.GetQueue() if err != nil { fmt.Println("读取数据到队列错误:", err) } // 联系多次获取单个数据 val, err := queueArr.GetOneQueue() if err != nil { fmt.Println(err) }else{ fmt.Println("获取当个数据:", val) } val, err = queueArr.GetOneQueue() if err != nil { fmt.Println(err) }else{ fmt.Println("获取当个数据:", val) } val, err = queueArr.GetOneQueue() if err != nil { fmt.Println(err) }else{ fmt.Println("获取当个数据:", val) } val, err = queueArr.GetOneQueue() if err != nil { fmt.Println(err) }else{ fmt.Println("获取当个数据:", val) } val, err = queueArr.GetOneQueue() if err != nil { fmt.Println(err) }else{ fmt.Println("获取当个数据:", val) } } 结果 [ `go run queueArr.go` | done ] 队列第1=0 队列第2=1 队列第3=2 获取当个数据: 0 获取当个数据: 1 获取当个数据: 2 队列为空 队列为空
三:环形数组队列
①:环形数组队列时对非环形数组队列的升级,可以有效的提高资源利用率,而不是一次性使用;
②:和非环形数组不同的是,环形数组需要预留一个空间作为尾索引(约定);
③:使用细节
③-1:(tail+1)%maxSize==head代表队列已满;
③-2:tail==head代表队列为空;
③-3:初始化时tail=0,head=0,不同于非环形队列的-1;
③-4:计算队列还有多少个元素(tail+maxSize-head)%maxSize
④:使用举例
package main
import (
"fmt"
"errors"
)
type CircleQueue struct{
MaxSize int
array [5]int
head int
tail int
}
//添加
func (this *CircleQueue) AddQueue(val int) (err error){
if (this.tail+1)%this.MaxSize == this.head{
return errors.New("队列已满")
}
// if(this.tail == this.MaxSize){
// this.tail = 0
// }
this.array[this.tail] = val
this.tail = (this.tail+1)%this.MaxSize
return
}
//展示所有
func (this *CircleQueue) GetQueue() (err error){
if this.head == this.tail {
return errors.New("队列为空")
}
for i := this.head; i != this.tail; i = (i+1)%this.MaxSize {
fmt.Printf("队列第%d=%v\n", i, this.array[i]);
}
return
}
//获取一个数据
func (this *CircleQueue) GetOneQueue() (val int, err error){
fmt.Println("index=", (this.head+this.MaxSize)%this.MaxSize)
if this.tail == this.head {
return 0, errors.New("队列为空")
}
val = this.array[(this.head+this.MaxSize)%this.MaxSize]
this.head = (this.head+1)%this.MaxSize
return val, err
}
func (this *CircleQueue) GetNum() (val int){
return (this.tail+this.MaxSize-this.head)%this.MaxSize
}
func main() {
//初始化环形队列
circleQueue := &CircleQueue{
MaxSize : 5,
head : 0,
tail : 0,
}
//添加数据
circleQueue.AddQueue(1)
circleQueue.AddQueue(2)
circleQueue.AddQueue(3)
circleQueue.AddQueue(4)
// circleQueue.AddQueue(5)
//读取所有数据
circleQueue.GetQueue()
//获取4个单个数据
val, err := circleQueue.GetOneQueue()
if err != nil {
fmt.Println(err)
}else{
fmt.Println(val)
}
err = circleQueue.AddQueue(5)
if err != nil {
fmt.Println(err)
}
circleQueue.GetQueue()
} 结果 [ `go run circleQueue.go` | done ] 队列第0=1
队列第1=2
队列第2=3
队列第3=4
index= 0
1
队列第1=2
队列第2=3
队列第3=4
队列第4=5