• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

数据结构Golang实现(六)——队列

武飞扬头像
小象裤衩
帮助1

队列

1. 顺序队列

1.1 结构定义

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()

// IsEmpty 判断队列是否为空
func (queue *SequentialQueue) IsEmpty() bool {
	return queue.Length == 0
}

1.3 IsFull()

// IsFull 判断队列是否为满
func (queue *SequentialQueue) IsFull() bool {
	return queue.Length == queue.Cap
}

1.4 Push()

// Push 将元素添加到该队列末尾
func (queue *SequentialQueue) Push(item any) {
	if queue.IsFull() {
		fmt.Println("队列已满")
		return
	}
	queue.Items = append(queue.Items, item)
	queue.Length  
}

1.5 Pop()

// 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()

// Peek 获取该队列首元素但不出队
func (queue *SequentialQueue) Peek() any {
	if queue.IsEmpty() {
		fmt.Println("空队列")
		return nil
	}
	return queue.Items[0]
}

1.7 Back()

// Back 获取该队列尾元素
func (queue *SequentialQueue) Back() any {
	if queue.IsEmpty() {
		fmt.Println("空队列")
		return nil
	}
	return queue.Items[queue.Length-1]
}

2. 链式队列

1.1 结构定义

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()

// IsEmpty 判断队列是否为空
func (queue *LinkedQueue) IsEmpty() bool {
	return queue.headNode == nil
}

1.3 Push()

// 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()

// 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()

// Peek 获取该队列首元素但不出队
func (queue *LinkedQueue) Peek() any {
	if queue.IsEmpty() {
		fmt.Println("空队列")
		return nil
	}
	return queue.headNode.Data
}

1.6 Back()

// Back 获取该队列尾元素但不出队
func (queue *LinkedQueue) Back() any {
	if queue.IsEmpty() {
		fmt.Println("空队列")
		return nil
	}
	return queue.tailNode.Data
}

1.7 Traverse()

// 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. 方案1:少使用一个位置
  2. 方案2:增加 Length 字段

方案1:少使用一个位置

1.1 结构定义
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()
// IsEmpty 判断队列是否为空
func (queue *LoopSeqQueue) IsEmpty() bool {
	return queue.Head == queue.Tail
}
1.3 IsFull()
// IsFull 判断队列是否已满
func (queue *LoopSeqQueue) IsFull() bool {
	return (queue.Tail 1)%queue.Cap == queue.Head // 解释:尾指针的下一个是否是头指针
}
1.4 Push()
// 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()
// 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()
// Peek 获取该队列首元素但不出队
func (queue *LoopSeqQueue) Peek() any {
	if queue.IsEmpty() {
		fmt.Println("空队列")
		return nil
	}
	return queue.Items[queue.Head]
}
1.7 Back()
// 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 结构定义
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()
// IsEmpty 判断队列是否为空
func (queue *LoopSeqQueue) IsEmpty() bool {
	return queue.Length == 0
}
1.3 IsFull()
// IsFull 判断队列是否已满
func (queue *LoopSeqQueue) IsFull() bool {
	return queue.Length == queue.Cap
}
1.4 Push()
// Push 将元素添加到该队列末尾
func (queue *LoopSeqQueue) Push(data any) {
	// 略 ... 同方案一
	queue.Length  
}
1.5 Pop()
// Pop 将该队列首元素弹出并返回
func (queue *LoopSeqQueue) Pop() any {
	// 略 ... 同方案一
	queue.Length--
	return data
}
1.6 Peek() 和 Back() 和方案一个一个地样

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1p11t0v32ihsm

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfaiea
系列文章
更多 icon
同类精品
更多 icon
继续加载