数据结构之队列(一般队列)

1. 什么是队列?

队列是一种特殊的线性表,一般只允许在队列的两端进行操作,队列前端进行删除操作,队列的末尾进行添加操作(双向队列的前端、末尾都可以进行删除、添加操作)。

队列可以用数组或链表实现。主要有两个指针:一个front指向队首元素,一个rear指向队尾元素。

 

 

 2. 队列常见操作

 

队列常用的操作有:

  • enqueue(e): 将元素e加入队尾
  • dequeue(): 返回队首元素,并将其从队列中移除
  • peek(): 返回队首元素的值,但不删除
  • size():返回队列中元素的个数
  • isEmpty(): 队列是否为空
  • show(): 返回队列的字符串形式

 

3. 队列的特点

·1. 线性数据结构

 2. 先进先出

 3. 有两个指针:一个front指向队首元素,一个rear指向队尾元素

 4. 一般队首进行出列,队尾进行入列

 5. 队列的长度是动态变化的,可以根据需要自动扩容或者缩减(特别注意数组实现队列时,可能会越界,需要扩容或缩进)。

 

4. 应用场景

队列是一种具有先进先出(FIFO)特性的数据结构,常用于需要按顺序处理数据的场景。以下是一些使用队列的示例:

  1. 消息队列:在消息系统中,消息发送者将消息添加到队列的尾部,而消息接收者从队列的头部获取消息进行处理。这种方式可以实现消息的异步处理,提高系统的并发能力。

  2. 请求排队:在服务器端,当有大量请求同时达到时,通过队列来对请求进行排队处理,以避免服务器过载。

  3. 生产者-消费者模型:在多线程或分布式系统中,生产者负责生成数据,消费者负责处理数据。通过队列作为缓冲区,可以实现生产者和消费者之间的解耦,提高系统的稳定性和性能。

  4. 广度优先搜索:在图论算法中,广度优先搜索通过队列来管理待访问的节点,实现对图的层次遍历。这在寻找最短路径等问题中非常常见。

  5. 缓存淘汰策略:在缓存系统中,当缓存空间不足时,可以使用队列来记录每个缓存项的访问时间,按照一定的策略删除最早访问的缓存项,以腾出空间给新的缓存项。

  6. 系统任务调度:在操作系统中,任务调度器可以使用队列来管理各个进程的执行顺序,按照优先级等规则进行调度。

  7. 打印机队列:打印机作为共享资源,当多个任务需要打印时,可以通过队列管理打印请求的顺序,避免打印机被多个任务同时访问。

总之,队列在很多需要按照顺序处理数据的场景中都有应用,它能够提供高效的插入和删除操作,并且保证元素的顺序性。

 5. Python

5.1 数组实现队列

复制代码
 1 '''
 2 数组实现队列
 3 '''
 4 
 5 
 6 class Queue:
 7     def __init__(self):
 8         self.items = []
 9 
10     def is_empty(self):
11         # 返回队列是否为空
12         return self.items == []
13 
14     def enqueue(self, item):
15         # 在队尾添加元素
16         self.items.append(item)
17 
18     def dequeue(self):
19         # 删除队首元素
20         if not self.is_empty():
21             return self.items.pop(0)
22 
23     def peek(self):
24         # 获取队首元素的值
25         if not self.is_empty():
26             return self.items[0]
27 
28     def size(self):
29         # 获取队列中的元素个数
30         return len(self.items)
31 
32     def __str__(self):
33         return str(self.items)
34 
35 
36 myQueue = Queue()
37 myQueue.enqueue(1)
38 myQueue.enqueue(2)
39 
40 print(myQueue.is_empty())  # 返回 False
41 print(myQueue.peek())  # 返回 1
42 print(myQueue.peek())  # 返回 1
43 
44 print(myQueue.dequeue())  # 1
45 print(myQueue.dequeue())  # 2
46 print(myQueue.is_empty())  # 返回 True
复制代码

输出:

1
2
3
4
5
6
False
1
1
1
2
True

  

5.2 链表实现队列示例

复制代码
 1 '''
 2 链表实现队列
 3 '''
 4 
 5 
 6 class Node():
 7     def __init__(self, data):
 8         self.data = data
 9         self.next = None
10 
11 
12 class Queue():
13     def __init__(self):
14         self.head = None
15         self.tail = None
16 
17     def enqueue(self, item):
18         if self.is_empty():  # 队列为空
19             self.head = Node(item)
20             self.tail = self.head
21         else:  # 队列不为空
22             node = Node(item)  # 创建一个节点
23             self.tail.next = node  # 把新节点接到尾部
24             self.tail = node  # 更新尾部指针
25 
26     def dequeue(self):
27 
28         if self.is_empty():  # 当队列为空时,返回None
29             return None
30         else:
31             cur = self.head
32             self.head = cur.next  # 删除第一个节点
33             if self.head is None:  # 如果删除后队列已经空了
34                 self.tail = None
35             return cur
36 
37     def is_empty(self):
38         return self.head is None
39 
40 
41 myQueue = Queue()
42 print(myQueue.is_empty())  # True
43 myQueue.enqueue(1)
44 myQueue.enqueue(2)
45 print(myQueue.is_empty())  # 返回 False
46 print(myQueue.dequeue().data)  # 返回 1
47 print(myQueue.dequeue().data)  # 返回 2
48 print(myQueue.is_empty())  # 返回 True
复制代码

输出:

1
2
3
4
5
True
False
1
2
True

 

6. Java

 

在Java中,可以使用数组来实现队列。具体实现的方式有以下几种:

  1. 使用固定长度的数组:可以创建一个固定长度的数组,然后使用指针指向队列的头部和尾部。当入队操作时,将元素添加到队列尾部,同时移动尾指针。当出队操作时,将头指针指向的元素删除,并将头指针向后移动一位。这种方式的缺点是队列的长度固定,不能动态调整。

  2. 使用循环数组:可以创建一个循环数组,使用两个指针分别指向队列的头部和尾部。当入队操作时,将元素添加到尾部,并将尾指针向后移动一位,如果尾指针超过了数组的长度,则将其重置为0。当出队操作时,将头指针指向的元素删除,并将头指针向后移动一位,如果头指针超过了数组的长度,则将其重置为0。这种方式可以实现队列的动态扩容。

  3. 使用LinkedList类:Java提供了LinkedList类,可以直接用来实现队列。LinkedList类实现了Queue接口,提供了队列的常见操作方法,如入队、出队、获取队首元素等。使用LinkedList类实现队列的好处是不需要手动处理数组的大小和扩容问题,同时具有较好的插入和删除性能。

复制代码
 1 import java.util.LinkedList;
 2 import java.util.Queue;
 3 
 4 public class QueueExample {
 5     public static void main(String[] args) {
 6         // 创建一个队列
 7         Queue<Integer> queue = new LinkedList<>();
 8 
 9         // 入队操作
10         queue.offer(1);
11         queue.offer(2);
12         queue.offer(3);
13 
14         // 出队操作
15         int firstElement = queue.poll();
16         System.out.println("出队元素:" + firstElement);
17 
18         // 获取队首元素(不出队列)
19         int frontElement = queue.peek();
20         System.out.println("队首元素:" + frontElement);
21 
22         // 获取队列中的元素个数
23         int size = queue.size();
24         System.out.println("队列大小:" + size);
25 
26         // 打印队列
27         System.out.println("队列内容:" + queue);
28     }
29 }
复制代码

输出:

1
2
3
4
出队元素:1
队首元素:2
队列大小:2
队列内容:[2, 3]

  

posted @   Allen_Hao  阅读(296)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示