队列
1. 顺序队列
1.1 结构定义
代码语言:javascript复制type SequentialQueue struct {
Items []any // 队列元素
Length uint64 // 队列元素个数
Cap uint64 // 队列容量
}
// NewSequentialQueue 初始化队列
func NewSequentialQueue(cap uint64) *SequentialQueue {
return &SequentialQueue{
Items: make([]any, 0, cap),
Length: 0,
Cap: cap,
}
}
1.2 IsEmpty()
代码语言:javascript复制// IsEmpty 判断队列是否为空
func (queue *SequentialQueue) IsEmpty() bool {
return queue.Length == 0
}
1.3 IsFull()
代码语言:javascript复制// IsFull 判断队列是否为满
func (queue *SequentialQueue) IsFull() bool {
return queue.Length == queue.Cap
}
1.4 Push()
代码语言:javascript复制// Push 将元素添加到该队列末尾
func (queue *SequentialQueue) Push(item any) {
if queue.IsFull() {
fmt.Println("队列已满")
return
}
queue.Items = append(queue.Items, item)
queue.Length
}
1.5 Pop()
代码语言:javascript复制// Pop 将该队列首元素弹出并返回
func (queue *SequentialQueue) Pop() any {
if queue.IsEmpty() {
fmt.Println("空队列")
return nil
}
item := queue.Items[0]
queue.Items = queue.Items[1:]
queue.Length--
return item
}
1.6 Peek()
代码语言:javascript复制// Peek 获取该队列首元素但不出队
func (queue *SequentialQueue) Peek() any {
if queue.IsEmpty() {
fmt.Println("空队列")
return nil
}
return queue.Items[0]
}
1.7 Back()
代码语言:javascript复制// Back 获取该队列尾元素
func (queue *SequentialQueue) Back() any {
if queue.IsEmpty() {
fmt.Println("空队列")
return nil
}
return queue.Items[queue.Length-1]
}
2. 链式队列
1.1 结构定义
代码语言:javascript复制type Node struct {
Data any
Next *Node
}
type LinkedQueue struct {
headNode *Node // 队首指针
length uint64
tailNode *Node // 队尾指针
}
// NewLinkedQueue 初始化队列
func NewLinkedQueue() *LinkedQueue {
return &LinkedQueue{}
}
1.2 IsEmpty()
代码语言:javascript复制// IsEmpty 判断队列是否为空
func (queue *LinkedQueue) IsEmpty() bool {
return queue.headNode == nil
}
1.3 Push()
代码语言:javascript复制// Push 将元素添加到该队列末尾
func (queue *LinkedQueue) Push(data any) {
node := &Node{Data: data}
if queue.IsEmpty() {
queue.headNode = node
queue.tailNode = node
return
}
queue.tailNode.Next = node
queue.tailNode = node
}
1.4 Pop()
代码语言:javascript复制// Pop 将该队列首元素弹出并返回
func (queue *LinkedQueue) Pop() any {
if queue.IsEmpty() {
fmt.Println("空队列")
return nil
}
data := queue.headNode.Data
queue.headNode = queue.headNode.Next
return data
}
1.5 Peek()
代码语言:javascript复制// Peek 获取该队列首元素但不出队
func (queue *LinkedQueue) Peek() any {
if queue.IsEmpty() {
fmt.Println("空队列")
return nil
}
return queue.headNode.Data
}
1.6 Back()
代码语言:javascript复制// Back 获取该队列尾元素但不出队
func (queue *LinkedQueue) Back() any {
if queue.IsEmpty() {
fmt.Println("空队列")
return nil
}
return queue.tailNode.Data
}
1.7 Traverse()
代码语言:javascript复制// Traverse 遍历队列
func (queue *LinkedQueue) Traverse() {
if queue.IsEmpty() {
fmt.Println("空队列")
return
}
currentNode := queue.headNode
for currentNode.Next != nil {
fmt.Printf("%v -> ", currentNode.Data)
currentNode = currentNode.Next
}
fmt.Println(currentNode.Data)
}
3. 循环队列
如果通过数组实现顺序队列的话,有一个问题,就是随着队列元素的插入和删除,队尾指针和队头指针不断后移,从而导致队尾指针指向末尾无法继续插入数据,这时候有可能队列头部还是有剩余空间的。 这时候就用到循环队列,这里提供两种实现方法:
方案1:少使用一个位置
方案2:增加 Length 字段
方案1:少使用一个位置
1.1 结构定义
代码语言:javascript复制type LoopSeqQueue struct {
Items []any
Head uint64 // 队首指针
Tail uint64 // 队尾指针
Cap uint64 // 队列容量
}
func NewLoopSeqQueue(cap uint64) *LoopSeqQueue {
return &LoopSeqQueue{
Items: make([]any, cap 1), // 因为有一个位置要空着
Head: 0,
Tail: 0, // [0,cap-1]
Cap: cap 1, // 因为有一个位置要空着
}
}
1.2 IsEmpty()
代码语言:javascript复制// IsEmpty 判断队列是否为空
func (queue *LoopSeqQueue) IsEmpty() bool {
return queue.Head == queue.Tail
}
1.3 IsFull()
代码语言:javascript复制// IsFull 判断队列是否已满
func (queue *LoopSeqQueue) IsFull() bool {
return (queue.Tail 1)%queue.Cap == queue.Head // 解释:尾指针的下一个是否是头指针
}
1.4 Push()
代码语言:javascript复制// Push 将元素添加到该队列末尾
func (queue *LoopSeqQueue) Push(data any) {
if queue.IsFull() {
fmt.Println("队列已满")
return
}
queue.Items[queue.Tail] = data
queue.Tail = (queue.Tail 1) % queue.Cap // 尾指针后移
}
1.5 Pop()
代码语言:javascript复制// Pop 将该队列首元素弹出并返回
func (queue *LoopSeqQueue) Pop() any {
if queue.IsEmpty() {
fmt.Println("空队列")
return nil
}
data := queue.Items[queue.Head]
queue.Head = (queue.Head 1) % queue.Cap // 头指针后移
return data
}
1.6 Peek()
代码语言:javascript复制// Peek 获取该队列首元素但不出队
func (queue *LoopSeqQueue) Peek() any {
if queue.IsEmpty() {
fmt.Println("空队列")
return nil
}
return queue.Items[queue.Head]
}
1.7 Back()
代码语言:javascript复制// Back 获取该队列尾元素但不出队
func (queue *LoopSeqQueue) Back() any {
if queue.IsEmpty() {
fmt.Println("空队列")
return nil
}
return queue.Items[(queue.Tail queue.Cap-1)%queue.Cap] // 因为 tail 指向的那个少用的位置,所以不可以直接return items[tail]
}
方案2:增加 Length 字段
1.1 结构定义
代码语言:javascript复制type LoopSeqQueue struct {
Items []any
Head uint64 // 队首指针
Tail uint64 // 队尾指针
Length uint64 // 队中元素个数
Cap uint64 // 队列容量
}
func NewLoopSeqQueue(cap uint64) *LoopSeqQueue {
return &LoopSeqQueue{
Items: make([]any, cap),
Head: 0,
Tail: 0, // [0,cap-1]
Length: 0,
Cap: cap,
}
}
1.2 IsEmpty()
代码语言:javascript复制// IsEmpty 判断队列是否为空
func (queue *LoopSeqQueue) IsEmpty() bool {
return queue.Length == 0
}
1.3 IsFull()
代码语言:javascript复制// IsFull 判断队列是否已满
func (queue *LoopSeqQueue) IsFull() bool {
return queue.Length == queue.Cap
}
1.4 Push()
代码语言:javascript复制// Push 将元素添加到该队列末尾
func (queue *LoopSeqQueue) Push(data any) {
// 略 ... 同方案一
queue.Length
}
1.5 Pop()
代码语言:javascript复制// Pop 将该队列首元素弹出并返回
func (queue *LoopSeqQueue) Pop() any {
// 略 ... 同方案一
queue.Length--
return data
}