队列简单入门

223 阅读3分钟

队列的特性是先进先出(FIFO),也就是说,最先进入队列的元素将最先被处理,而最后进入队列的元素将最后被处理。队列可以用于许多不同的应用程序,例如在操作系统中进行进程调度,网络路由中传输数据包,或在游戏中管理玩家的行动。

什么是队列

队列是一种基本的数据结构,在计算机科学中有广泛的应用。队列的基本概念是先进先出(FIFO),它的操作类似于现实生活中排队等待的过程。最先进入队列的元素将最先被处理,而最后进入队列的元素将最后被处理。

队列的应用

队列可以用于许多不同的应用程序,例如

  1. 在操作系统中进行进程调度,网络路由中传输数据包,或在游戏中管理玩家的行动。
  2. 在操作系统中,进程被排列在一个队列中,按照它们被提交的顺序来运行。
  3. 在网络路由中,数据包被传输到目的地,按照它们被接收的顺序来处理。
  4. 在游戏中,玩家的行动被加入到一个队列中,以确保每个玩家按照他们的顺序进行操作。

另外一类比较有名的程序叫做:消息队列。可以作为削峰平谷的中间件来使用。

基本操作

队列通常具有两个基本操作:入队和出队。入队操作将一个元素添加到队列的末尾,而出队操作则将队列的第一个元素弹出并返回。队列还可以支持其他操作,例如查看队列的第一个元素,检查队列是否为空,或清空整个队列。这些操作使得队列成为一种非常灵活和有用的数据结构。

代码实现

队列可以使用数组或链表实现。数组实现的队列通常具有固定的大小,而链表实现的队列可以支持动态大小调整。

这里还是只提供数组的实现:

 package main
 ​
 import "fmt"
 ​
 type Queue struct {
     items []int
 }
 ​
 func (q *Queue) Enqueue(item int) {
     q.items = append(q.items, item)
 }
 ​
 func (q *Queue) Dequeue() int {
     if len(q.items) == 0 {
         panic("Queue is empty")
     }
     item := q.items[0]
     q.items = q.items[1:]
     return item
 }
 ​
 func (q *Queue) IsEmpty() bool {
     return len(q.items) == 0
 }
 ​
 func main() {
     q := Queue{}
     q.Enqueue(1)
     q.Enqueue(2)
     q.Enqueue(3)
     fmt.Println(q.Dequeue()) // 1
     fmt.Println(q.Dequeue()) // 2
     fmt.Println(q.IsEmpty()) // false
     fmt.Println(q.Dequeue()) // 3
     fmt.Println(q.IsEmpty()) // true
 }

队列与二叉树

在对二叉树进行层次遍历的时候,常常使用队列做为辅助。

一般的思路是:

先将一层(最开始只有根节点)的数据加入队列中,然后循环当前的队列的长度 len 次。

每次将队首元素节点弹出队列,取出该节点的值加入结果中,然后将该节点的左右子节点加入队列。

循环完 len 次后,一层的节点已经全部遍历完毕,剩下在队列中的节点均为下一层的节点。

继续进行 len 次的循环直到遍历完所有的节点。

这里给出一道Leetcode题目和AC代码:

原题:

102. 二叉树的层序遍历 - 力扣(Leetcode)

AC代码:

 /**
  * Definition for a binary tree node.
  * type TreeNode struct {
  *     Val int
  *     Left *TreeNode
  *     Right *TreeNode
  * }
  */
 func levelOrder(root *TreeNode) [][]int {
     // 如果队列为空,则直接返回
     if root == nil {
         return [][]int{}
     }
     results := make([][]int, 0)
     q := make([]*TreeNode, 1)
     // 将根节点加入队列
     q[0] = root
     for len(q) > 0 {
         length := len(q)
         // 新建表示一层的节点的数组
         result := make([]int, 0, length)
         // 执行 length 次
         for i := 0; i < length; i++ {
             // 弹出队首节点
             node := q[0]
             q = q[1:]
             // 将该节点的值加入数组
             result = append(result, node.Val)
             // 将该节点的左右非空子节点加入队列
             if node.Left != nil {
                 q = append(q, node.Left)
             }
             if node.Right != nil {
                 q = append(q, node.Right)
             }
         }
         // 执行完 length 之后,数组中为该层所有的节点值,队列中为该层的下一层所有的节点值
         results = append(results, result)
     }
     return results
 }