队列介绍
- 队列是一个有序列表,可以用数组或是链表来实现
- 遵循先入先出的原则,即:先存入队列的数据,要先取出。后存入的要后取出
-
数组模拟单向队列
maxsize是该队列的最大容量, front随着数据的输出而改变,rear随着数据的输入而改变,
这里front=-1,rear=2,当存入数据时,rear=maxsize-1,队列刚好满
思路:
单向数组队列:
package main
import (
"fmt"
"github.com/pkg/errors"
"os"
)
type Queue struct {
maxSize int //队列容量
array [5]int//数组->模拟队列
front int //表示指向队列的首部
rear int //表示指向队列的尾部
}
//添加数据到队列
func (this *Queue) AddQueue(val int) (err error) {
//先判断队列是否已经满了
if this.rear == this.maxSize-1{//队列刚好满了
return errors.New("队列满了")
}
this.rear++ //尾指针后移
this.array[this.rear] =val //将传来的值放入队列
return
}
//从队列中取出数据
func (this *Queue) GetQueue() (val int, err error) {
//先判断队列是否为空
if this.rear == this.front { //队空
return -1, errors.New("队列为空")
}
this.front++
val = this.array[this.front]
return val ,err
}
//显示队列,找到队首,然后遍历到队尾
func (this *Queue) ShowQueue() {
//this.front初始值为-1
for i := this.front + 1;i <= this.rear;i++{
fmt.Printf("array[%d]=%d\t",i,this.array[i])
}
fmt.Println()
}
//主函数
func main() {
//先创建一个队列
queue := &Queue{
maxSize : 5,
front : -1,
rear : -1,
}
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)
}
}
}
-
数组模拟环形队列
上面的代码实现了基本的队列结构,但是没有有效的利用数组空间,可以使用数组实现一个环形队列解决,如何实现呢?
可以通过取模的方式实现
注意:尾指针的下一个为头指针时表示队列满,即将队列空出一个容量作为约定,
(1)(rear + 1)% maxsize == front表示队列满
(2) rear==front表示队列空
(3) 初始化时,front =0 ,rear = 0
(4) 怎么统计该队列一共多少元素?(rear + maxsize -head)%maxsize
代码实现:
package main
import (
"fmt"
"github.com/pkg/errors"
"os"
)
//使用一个结构体管理环形队列
type RoundQueue struct {
maxSize int
array [5]int
front int //头指针
rear int //尾指针
}
//将数字入队列
func (this *RoundQueue) AddQueue(val int)(err error){
if this.IsFull(){
return errors.New("队列满,放入失败")
}
this.array[this.rear] = val
this.rear = (this.rear + 1) % this.maxSize
return
}
//从队列中拿出数字
func (this *RoundQueue) GetQueue()(val int,err error){
if this.IsEmpty() {
return 0,errors.New("队列空")
}
val = this.array[this.front]
this.front = (this.front +1) % this.maxSize
return
}
//判断环形队列是否满,返回true为满
func (this *RoundQueue) IsFull() bool {
return (this.rear + 1) % this.maxSize == this.front
}
//判断环形队列是否空,返回true为空
func (this *RoundQueue) IsEmpty() bool {
return this.rear == this.front
}
//返回队列中的元素总数
func (this *RoundQueue) Size() int {
return (this.rear + this.maxSize -this.front) % this.maxSize
}
//显示队列
func (this *RoundQueue) ShowQueue() {
//取出当前队列有多少个元素
size := this.Size()
if size == 0{
fmt.Println("队列为空")
}
//设计一个辅助变量,指向头指针
temHead := this.front
for i :=0;i < size ;i++{
fmt.Printf("array[%d]=%d\t",temHead,this.array[temHead])
temHead = (temHead + 1) % this.maxSize
}
fmt.Println()
}
//主函数
func main() {
//初始化环形队列
queue := &RoundQueue{
maxSize : 5,
front : 0,
rear : 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("加入队列成功")
}
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)
}
}
}