package main
import (
"errors"
"fmt"
)
// 队列
// 特征:
// 1. 按照元素的添加顺序排序,并且容量固定
// 2. 添加元素,放入末尾
// 3. 移出元素,将最先加入的元素移出
// 4. First In First Out -> FIFO
// 实现(头指针 + 尾指针 + 保存元素的元组):
// 1. 数组
// 2. 链表
// 思路:
// 1. 头指针 + 尾指针 + 保存元素的元组
// 2. 两个方法 Add() Get()
// 3. 判空 empty,判满 full
// Go 实现队列思路
// 1. queue结构体, buf存储数据, head通过切片下标指向队列头部,tail通过切片下标指向队列尾部,但tail指向的下标不存放元素
// 2. 添加元素使用 Push方法,移动tail指针,如果 tail指针值超过最大值,则重置tail指针指向0, overFlow置为 true
// 3. 读取元素使用 Pop方法,移动head指针,如果head指针等于最大值,则重置head指针为0, overflown置为false
// 4. 判空:如果 overflown为false且 head = tail时候为空
// 5. 判满: 如果 overflown为false且 tail = maxSize 时为满,如果overflown为true且 tail -1 = head 时候为满
// 难点: 什么时候head 和 tail指针归0,如何空与判满
// queue 模拟队列
type queue struct {
// buf 存放元素
buf []int
// 一个指向队列的头部,一个指向尾部,但尾部指向的位置不包含元素
head, tail int
// 判断头部是否溢出
overflow bool
maxSize int
}
func NewQueue(size int) *queue {
return &queue{
buf : make([]int, size + 1),
maxSize: size,
}
}
// Push 向队列中添加一个元素
func (q *queue) Push(elem int) (err error) {
// 1. 判满
if q.overflow {
if q.tail - 1 == q.head {
err = errors.New("Q 满")
fmt.Println(err)
return err
}
} else {
if q.tail == q.maxSize {
err = errors.New("Q 满")
return err
}
}
// 1. 添加元素,应该头指针指向的下标不存储元素
q.tail ++
q.buf[q.tail - 1] = elem
// 如果 q.tail 结果为maxSize则值为0
if q.tail == q.maxSize {
q.tail = 0
q.overflow = true
}
return
}
// Pop 从队列中移出一个元素
func (q *queue) Pop() (elem int, err error) {
// 1. 判空
if !q.overflow {
if q.tail == q.head {
err = errors.New("Q 空")
fmt.Println(err)
return -1, err
}
}
// 1. 移出元素,获取头指针指向的元素,并且将头指针加上1
elem = q.buf[q.head]
q.head ++
// 2. 如果 q.head 值等于最大值则重置为0
if q.head == q.maxSize {
q.head = 0
q.overflow = false
}
return
}
// Show 显示队列中的元素
func (q *queue) Show() {
data := make([]int, 0 , q.maxSize)
if q.overflow {
data = append(data, q.buf[:q.tail]...)
data = append(data, q.buf[q.head:q.maxSize]...)
} else {
data = append(data, q.buf[q.head:q.tail]...)
}
fmt.Println(data)
}
func main() {
q := NewQueue(3)
q.Push(3)
q.Push(4)
q.Push(5)
q.Pop()
q.Pop()
q.Pop()
q.Pop()
q.Pop()
q.Show()
q.Pop()
q.Show()
}