基本介绍
- 队列是一个有序列表,可以用数组或是链表来实现。
- 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
栈: 先入后出(弹夹)
队首 , 队尾
数组模拟环形队列
使用数组实现简单队列的思路
非环
- 创建一个数组arrary,是作为队列的一个字段
- front初始化为-1
- rear, 表示队列尾部,初始化为-1
- 完成队列的基本查找
AddQueue // 加入数据到队列
GetQueue // 从队列取出数据
ShowQueue // 显示队列
代码实现(非环队列)
// 数组模拟队列
// 非环队列
package main
import (
"errors"
"fmt"
"os"
)
/*
1. 创建一个数组arrary,是作为队列的一个字段
2. front初始化为-1
3. rear, 表示队列尾部,初始化为-1
4. 完成队列的基本查找
AddQueue // 加入数据到队列
GetQueue // 从队列取出数据
ShowQueue // 显示队列
*/
type Queue struct {
maxSize int
array [4]int // 数组模拟队列
front int // 队列首(下标index), 不包含队首的元素
rear int // 队列尾(下标index)
}
// 添加数据到队列 - 入队列
func (que *Queue) AddQueue(val int) (err error) {
// 先判断队列是否已满
if que.rear == que.maxSize-1 {
return errors.New("queue full")
}
que.rear++ // rear 后移
que.array[que.rear] = val
fmt.Println("front = ", que.front, "rear = ", que.rear, "array = ", que.array)
return
}
// 显示队列
func (que *Queue) ShowQueue() {
fmt.Println("显示队列: ")
fmt.Println("front = ", que.front, "rear = ", que.rear, "array = ", que.array)
// front初始值是 -1, 不包含队首的元素
for i := que.front + 1; i <= que.rear; i++ {
fmt.Printf("array[%d] = %d\n", i, que.array[i])
}
fmt.Println()
}
// 出队列
func (que *Queue) GetQueue() (val int, err error) {
// 判断队列是否是空
if que.rear == que.front {
return -1, errors.New("queue empty")
}
que.front++
val = que.array[que.front]
que.array[que.front] = 0
fmt.Println("front = ", que.front, "rear = ", que.rear, "array = ", que.array)
return val, err
}
func main() {
queue := &Queue{
maxSize: 4,
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("加入队列成功")
} else {
fmt.Println(err.Error())
}
case "get":
val, err := queue.GetQueue()
if err == nil {
fmt.Println("取到的值:", val)
} else {
fmt.Println(err.Error())
}
case "show":
queue.ShowQueue()
case "exit":
os.Exit(0)
default:
fmt.Println("输入有误,请重新输入")
}
}
}
/*
get
front = 2 rear = 3 array = [0 0 0 4]
取到的值: 3
1. 输入 add 表示添加数据到队列
2. 输入 get 表示从队列中获取数据
3. 输入 show 表示显示队列
4. 输入 exit 表示退出
get
front = 3 rear = 3 array = [0 0 0 0]
取到的值: 4
1. 输入 add 表示添加数据到队列
2. 输入 get 表示从队列中获取数据
3. 输入 show 表示显示队列
4. 输入 exit 表示退出
get
queue empty
*/
数组模拟环形队列
分析思路:
什么时候表示队列满
(tail + 1) % maxSize = head
tail == head 表示空
- 初始化时, tail = 0 head = 0
- 环形实现: tail = (tail + 1) % maxSize, head = (head + 1) % maxSize
核心思想:到达队尾的时候,通过 加1取模 的方式回到队首
- 怎么统计该队列有多少个元素
(tail + maxSize - head ) % maxSize
代码实现
// 数组模拟环形队列(有缺口)
package main
import (
"errors"
"fmt"
"os"
)
/*
分析思路:
1. 什么时候表示队列满
(tail + 1) % maxSize == head
2. tail == head 表示空
3. 初始化时, tail = 0 head = 0
4. 怎么统计该队列有多少个元素
(tail + maxSize - head ) % maxSize
*/
type CircleQueue struct {
maxSize int
array [5]int
head int // 队首, 初始 0
tail int // 队尾, 初始 0
}
// 判断环形队列是否已满
func (que *CircleQueue) IsFull() bool {
fmt.Println("IsFull --- head", que.head, "tail", que.tail)
return (que.tail+1)%que.maxSize == que.head
}
// 判断环形队列是否为空
func (que *CircleQueue) IsEmpty() bool {
return que.tail == que.head
}
// 环形队列所有元素
func (que *CircleQueue) Size() int {
return (que.tail + que.maxSize - que.head) % que.maxSize
}
// 入队列
func (que *CircleQueue) Push(val int) (err error) {
// 先判断队列是否已满
if que.IsFull() {
return errors.New("CircleQueue full")
}
que.array[que.tail] = val
fmt.Println("head = ", que.head, "tail = ", que.tail, "array = ", que.array)
// que.tail = (que.tail + 1) % que.maxSize
que.tail = (que.tail + 1) % len(que.array)
// que.tail++ // tail 后移
return
}
// 出队列
func (que *CircleQueue) Pop() (val int, err error) {
// 判断队列是否是空
if que.IsEmpty() {
return 0, errors.New("CircleQueue empty")
}
val = que.array[que.head]
que.array[que.head] = 0
fmt.Println("Pop --- head = ", que.head, "tail = ", que.tail, "array = ", que.array)
que.head = (que.head + 1) % que.maxSize
return val, err
}
// 显示队列
func (que *CircleQueue) ShowQueue() {
fmt.Println("显示队列: ")
size := que.Size()
if size == 0 {
fmt.Println("队列为空")
}
tempHead := que.head
for i := 0; i < size; i++ {
fmt.Printf("arr[%d]=%d\t", tempHead, que.array[tempHead])
tempHead = (tempHead + 1) % que.maxSize
}
fmt.Println()
fmt.Println("head = ", que.head, "tail = ", que.tail, "array = ", que.array)
fmt.Println()
}
func main() {
circleQueue := &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 := circleQueue.Push(val)
if err == nil {
fmt.Println("加入队列成功")
} else {
fmt.Println(err.Error())
}
case "get":
fmt.Println("取出")
val, err := circleQueue.Pop()
if err == nil {
fmt.Println("取到的值:", val)
} else {
fmt.Println(err.Error())
}
case "show":
circleQueue.ShowQueue()
case "exit":
os.Exit(0)
default:
fmt.Println("输入有误,请重新输入")
}
}
}
/*
get
取出
Pop --- head = 1 tail = 0 array = [0 0 3 4 5]
取到的值: 2
1. 输入 add 表示添加数据到队列
2. 输入 get 表示从队列中获取数据
3. 输入 show 表示显示队列
4. 输入 exit 表示退出
add
请输入要入队列的数
6
IsFull --- head 2 tail 0
head = 2 tail = 0 array = [6 0 3 4 5]
加入队列成功
1. 输入 add 表示添加数据到队列
2. 输入 get 表示从队列中获取数据
3. 输入 show 表示显示队列
4. 输入 exit 表示退出
show
显示队列:
arr[2]=3 arr[3]=4 arr[4]=5 arr[0]=6
head = 2 tail = 1 array = [6 0 3 4 5]
*/