正在载入交互式动画窗口请稍等
队列-顺序表 可视化交互式动画版
与Stack 类似 , Queue 是一种线性数据结构,遵循特定的顺序执行存储数据的操作。 顺序是先进先出 (FIFO) 。
人们可以将队列想象成一队人从队列的开头开始按顺序等待接收某些东西。 它是一个有序列表,其中插入是在一端(称为后部)完成的,删除是从另一端(称为前部)完成的。 队列的一个很好的例子是资源的任何消费者队列,其中先到达的消费者首先得到服务。
栈和队列的区别在于删除。 在堆栈中,我们删除最近添加的项目; 在队列中,我们删除最近最少添加的项目。
队列的基本操作:
- enqueue(): 将一个元素插入到队列的末尾,即后端。
- dequeue(): 此操作删除并返回位于队列前端的元素。
- front(): 该操作返回前端的元素,但不删除它。
- after(): 该操作返回后端的元素,但不删除它。
- isEmpty(): 该操作指示队列是否为空。
- isFull(): 该操作指示队列是否已满。
- size(): 此操作返回队列的大小,即队列包含的元素总数。
队列类型:
- 简单队列: 简单队列也称为线性队列,是队列的最基本版本。 这里,插入元素即入队操作发生在后端,移除元素即出队操作发生在前端。 这里的问题是,如果我们从前面弹出一些项目,然后后面达到队列的容量,虽然前面有空白意味着队列未满,但根据 isFull() 函数中的条件,它将显示那么队列已满。 为了解决这个问题我们使用 循环队列 。
- 循环队列 : 在循环队列中,队列的元素充当圆环。 循环队列的工作原理与线性队列类似,只是最后一个元素连接到第一个元素。 它的优点是可以更好地利用内存。 这是因为如果存在空白空间,即如果队列中的某个位置不存在元素,则可以使用模容量(%n)轻松地在该位置添加 元素 。
- 优先队列 : 该队列是一种特殊类型的队列。 它的特点是它根据某种优先级排列队列中的元素。 优先级可以是具有最高值的元素具有优先级,因此它创建一个按值降序排列的队列。 优先级也可以是具有最低值的元素获得最高优先级,因此它依次创建一个值顺序递增的队列。 在预定义优先级队列中,C++优先考虑最高值,而Java优先考虑最低值。
- 出队 : 出队也称为双端队列。 顾名思义,双端队列意味着可以从队列的两端插入或删除一个元素,这与其他队列只能从一端插入或删除元素不同。 由于此属性,它可能不遵守先进先出属性。
队列的应用:
当事物不需要立即处理,但必须 像 广度 优先 搜索 那样以先入 先 出 的 顺序处理 时,就会使用 队列 。 队列的这一属性使其在以下场景中也很有用。
- 当资源在多个消费者之间共享时。 示例包括 CPU 调度、磁盘调度。
- 当数据在两个进程之间异步传输时(数据接收速率不一定与发送速率相同)。 示例包括 IO 缓冲区、管道、文件 IO 等。
- 队列可以用作各种其他数据结构的重要组成部分。
队列的数组实现:
为了实现队列,我们需要跟踪两个索引:前索引和后索引。 我们在后面将一个项目入队,并从前面将一个项目出队。 如果我们只是简单地增加前部和后部索引,那么可能会出现问题,前部可能会到达数组的末尾。 解决这个问题的办法就是以循环的方式增加前后。
入队步骤:
- 检查队列是否已满
- 如果已满,则打印溢出并退出
- 如果队列未满,则增加tail并添加元素
出队步骤:
- 检查队列是否为空
- 如果为空,则打印下溢并退出
- 如果不为空,则打印头部元素并增加头部
下面是一个在队列上实现上述操作的程序
- C++
- C
- Java
- Python3
- C#
- JavaScript
C++
// CPP program for array
// implementation of queue
#include <bits/stdc++.h> using namespace std; // A structure to represent a queue class Queue { public : int
front, rear, size; unsigned capacity; int * array; }; // function to create a queue // of given capacity.
// It initializes size of queue as 0 Queue* createQueue(unsigned capacity) { Queue* queue = new Queue(); queue->capacity = capacity; queue->front = queue->size = 0; // This is important, see the enqueue queue->rear = capacity - 1; queue->array = new int [queue->capacity]; return queue; } // Queue is full when size
// becomes equal to the capacity int isFull(Queue* queue) { return (queue->size == queue->capacity); } // Queue is empty when size is 0 int isEmpty(Queue* queue) { return (queue->size == 0); } // Function to add an item to the queue. // It changes rear and size void enqueue(Queue* queue, int item) { if
(isFull(queue)) return ; queue->rear = (queue->rear + 1) % queue->capacity; queue->array[queue->rear] = item; queue->size = queue->size + 1; cout << item << " enqueued to queue\n" ; } // Function to remove an item from queue. // It changes front and size int dequeue(Queue* queue) { if
(isEmpty(queue)) return INT_MIN; int
item = queue->array[queue->front]; queue->front = (queue->front + 1) % queue->capacity; queue->size = queue->size - 1; return item; } // Function to get front of queue int front(Queue* queue) { if
(isEmpty(queue)) return INT_MIN; return queue->array[queue->front]; } // Function to get rear of queue int rear(Queue* queue) { if
(isEmpty(queue)) return INT_MIN; return queue->array[queue->rear]; } // Driver code int main() { Queue* queue = createQueue(1000); enqueue(queue, 10); enqueue(queue, 20); enqueue(queue, 30); enqueue(queue, 40); cout << dequeue(queue) << " dequeued from queue\n" ; cout << "Front item is " << front(queue) << endl; cout << "Rear item is " << rear(queue) << endl; return 0; } // This code is contributed by rathbhupendra |
C
Java
Python3
C#
JavaScript
10 已排队 20 已排队 30 已排队 40 正在排队 10 已从队列中出队 前面的项目是 20 后面的项目是 40
复杂度分析:
- 时间复杂度
运营 | 复杂 |
---|---|
入队(插入) | 复杂度(1) |
双端队列(删除) | 复杂度(1) |
前面(取得前面) | 复杂度(1) |
后部(获得后部) | 复杂度(1) |
IsFull(检查队列是否已满) | 复杂度(1) |
IsEmpty(检查队列是否为空) | 复杂度(1) |
-
辅助空间:
O(N),其中 N 是用于存储元素的数组的大小。
数组实现的优点:
- 易于实施。
- 可以轻松有效地管理大量数据。
- 由于遵循先进先出的规则,可以轻松执行插入和删除等操作。
数组实现的缺点:
- 静态数据结构,固定大小。
- 如果队列有大量的入队和出队操作,在某个时刻(前后索引线性递增的情况下)我们可能无法在队列为空的情况下插入元素(这个问题可以避免)通过使用循环队列)。
- 必须事先定义队列的最大大小。