原文: https://www.programiz.com/dsa/queue

在本教程中,您将学习什么是队列。 此外,您还将发现使用 C,C++ ,Java 和 Python 实现队列的实现。

队列是编程中有用的数据结构。 它类似于电影院大厅外面的售票队列,在该队列中,第一个进入队列的人是第一个获得票的人。

队列遵循先进先出(FIFO)规则-先进入的项目也是先出来的项目。

队列 - 图1

FIFO 表示

在上图中,由于 1 在 2 之前保留在队列中,因此它也是第一个从队列中删除的队列。 它遵循 FIFO 规则。

用编程术语来说,将项目放入队列称为“入队”,而将项目从队列中删除则称为“出队”。

我们可以使用任何编程语言(例如 C,C++ ,Java,Python 或 C# )来实现队列,但是规范几乎是相同的。


队列规范

队列是一个对象,或更具体地说,是一个允许执行以下操作的抽象数据结构(ADT):

  • enqueue:将元素添加到队列的末尾
  • dequeue:从队列的开头删除元素
  • IsEmpty:检查队列是否为空
  • IsFull:检查队列是否已满
  • peek:获取队列前面的值而不删除它

队列如何工作

队列操作如下:

  1. 两个称为FRONTREAR的指针用于跟踪队列中的第一个和最后一个元素。
  2. 初始化队列时,我们将FRONTREAR的值设置为 -1。
  3. 排队元素时,我们增加REAR索引的值,并将新元素放置在REAR指向的位置。
  4. 在元素出队时,我们返回FRONT指向的值,并增加FRONT索引。
  5. 在排队之前,我们检查队列是否已满。
  6. 在出队之前,我们检查队列是否已经为空。
  7. 当对第一个元素进行排队时,我们将FRONT的值设置为 0。
  8. 使最后一个元素出队时,我们将FRONTREAR的值重置为 -1。

队列 - 图2

队列操作的原理


Python,Java 和 C/C++ 示例

最常见的队列实现是使用数组,但是也可以使用列表来实现。

  1. # Queue implementation in Python
  2. class Queue:
  3. def __init__(self):
  4. self.queue = []
  5. # Add an element
  6. def enqueue(self, item):
  7. self.queue.append(item)
  8. # Remove an element
  9. def dequeue(self):
  10. if len(self.queue) < 1:
  11. return None
  12. return self.queue.pop(0)
  13. # Display the queue
  14. def display(self):
  15. print(self.queue)
  16. def size(self):
  17. return len(self.queue)
  18. q = Queue()
  19. q.enqueue(1)
  20. q.enqueue(2)
  21. q.enqueue(3)
  22. q.enqueue(4)
  23. q.enqueue(5)
  24. q.display()
  25. q.dequeue()
  26. print("After removing an element")
  27. q.display()
  1. // Queue implementation in Java
  2. public class Queue {
  3. int SIZE = 5;
  4. int items[] = new int[SIZE];
  5. int front, rear;
  6. Queue() {
  7. front = -1;
  8. rear = -1;
  9. }
  10. boolean isFull() {
  11. if (front == 0 && rear == SIZE - 1) {
  12. return true;
  13. }
  14. return false;
  15. }
  16. boolean isEmpty() {
  17. if (front == -1)
  18. return true;
  19. else
  20. return false;
  21. }
  22. void enQueue(int element) {
  23. if (isFull()) {
  24. System.out.println("Queue is full");
  25. } else {
  26. if (front == -1)
  27. front = 0;
  28. rear++;
  29. items[rear] = element;
  30. System.out.println("Inserted " + element);
  31. }
  32. }
  33. int deQueue() {
  34. int element;
  35. if (isEmpty()) {
  36. System.out.println("Queue is empty");
  37. return (-1);
  38. } else {
  39. element = items[front];
  40. if (front >= rear) {
  41. front = -1;
  42. rear = -1;
  43. } /* Q has only one element, so we reset the queue after deleting it. */
  44. else {
  45. front++;
  46. }
  47. System.out.println("Deleted -> " + element);
  48. return (element);
  49. }
  50. }
  51. void display() {
  52. /* Function to display elements of Queue */
  53. int i;
  54. if (isEmpty()) {
  55. System.out.println("Empty Queue");
  56. } else {
  57. System.out.println("\nFront index-> " + front);
  58. System.out.println("Items -> ");
  59. for (i = front; i <= rear; i++)
  60. System.out.print(items[i] + " ");
  61. System.out.println("\nRear index-> " + rear);
  62. }
  63. }
  64. public static void main(String[] args) {
  65. Queue q = new Queue();
  66. // deQueue is not possible on empty queue
  67. q.deQueue();
  68. // enQueue 5 elements
  69. q.enQueue(1);
  70. q.enQueue(2);
  71. q.enQueue(3);
  72. q.enQueue(4);
  73. q.enQueue(5);
  74. // 6th element can't be added to queue because queue is full
  75. q.enQueue(6);
  76. q.display();
  77. // deQueue removes element entered first i.e. 1
  78. q.deQueue();
  79. // Now we have just 4 elements
  80. q.display();
  81. }
  82. }
  1. // Queue implementation in C
  2. #include <stdio.h>
  3. #define SIZE 5
  4. void enQueue(int);
  5. void deQueue();
  6. void display();
  7. int items[SIZE], front = -1, rear = -1;
  8. int main() {
  9. //deQueue is not possible on empty queue
  10. deQueue();
  11. //enQueue 5 elements
  12. enQueue(1);
  13. enQueue(2);
  14. enQueue(3);
  15. enQueue(4);
  16. enQueue(5);
  17. //6th element can't be added to queue because queue is full
  18. enQueue(6);
  19. display();
  20. //deQueue removes element entered first i.e. 1
  21. deQueue();
  22. //Now we have just 4 elements
  23. display();
  24. return 0;
  25. }
  26. void enQueue(int value) {
  27. if (rear == SIZE - 1)
  28. printf("\nQueue is Full!!");
  29. else {
  30. if (front == -1)
  31. front = 0;
  32. rear++;
  33. items[rear] = value;
  34. printf("\nInserted -> %d", value);
  35. }
  36. }
  37. void deQueue() {
  38. if (front == -1)
  39. printf("\nQueue is Empty!!");
  40. else {
  41. printf("\nDeleted : %d", items[front]);
  42. front++;
  43. if (front > rear)
  44. front = rear = -1;
  45. }
  46. }
  47. // Function to print the queue
  48. void display() {
  49. if (rear == -1)
  50. printf("\nQueue is Empty!!!");
  51. else {
  52. int i;
  53. printf("\nQueue elements are:\n");
  54. for (i = front; i <= rear; i++)
  55. printf("%d ", items[i]);
  56. }
  57. printf("\n");
  58. }
  1. // Queue implementation in C++
  2. #include <iostream>
  3. #define SIZE 5
  4. using namespace std;
  5. class Queue {
  6. private:
  7. int items[SIZE], front, rear;
  8. public:
  9. Queue() {
  10. front = -1;
  11. rear = -1;
  12. }
  13. bool isFull() {
  14. if (front == 0 && rear == SIZE - 1) {
  15. return true;
  16. }
  17. return false;
  18. }
  19. bool isEmpty() {
  20. if (front == -1)
  21. return true;
  22. else
  23. return false;
  24. }
  25. void enQueue(int element) {
  26. if (isFull()) {
  27. cout << "Queue is full";
  28. } else {
  29. if (front == -1) front = 0;
  30. rear++;
  31. items[rear] = element;
  32. cout << endl
  33. << "Inserted " << element << endl;
  34. }
  35. }
  36. int deQueue() {
  37. int element;
  38. if (isEmpty()) {
  39. cout << "Queue is empty" << endl;
  40. return (-1);
  41. } else {
  42. element = items[front];
  43. if (front >= rear) {
  44. front = -1;
  45. rear = -1;
  46. } /* Q has only one element, so we reset the queue after deleting it. */
  47. else {
  48. front++;
  49. }
  50. cout << endl
  51. << "Deleted -> " << element << endl;
  52. return (element);
  53. }
  54. }
  55. void display() {
  56. /* Function to display elements of Queue */
  57. int i;
  58. if (isEmpty()) {
  59. cout << endl
  60. << "Empty Queue" << endl;
  61. } else {
  62. cout << endl
  63. << "Front index-> " << front;
  64. cout << endl
  65. << "Items -> ";
  66. for (i = front; i <= rear; i++)
  67. cout << items[i] << " ";
  68. cout << endl
  69. << "Rear index-> " << rear << endl;
  70. }
  71. }
  72. };
  73. int main() {
  74. Queue q;
  75. //deQueue is not possible on empty queue
  76. q.deQueue();
  77. //enQueue 5 elements
  78. q.enQueue(1);
  79. q.enQueue(2);
  80. q.enQueue(3);
  81. q.enQueue(4);
  82. q.enQueue(5);
  83. //6th element can't be added to queue because queue is full
  84. q.enQueue(6);
  85. q.display();
  86. //deQueue removes element entered first i.e. 1
  87. q.deQueue();
  88. //Now we have just 4 elements
  89. q.display();
  90. return 0;
  91. }

此实现的局限性

如您在下图中所看到的,经过一些入队和出队后,队列的大小已减小。

队列 - 图3

队列限制

只有当所有元素都已出队后,才能在重置队列后使用索引 0 和 1。

REAR到达最后一个索引之后,如果我们可以在空白空间(0 和 1)中存储额外的元素,则可以利用这些空白空间。 这通过称为循环队列的修改队列来实现。


队列复杂度

使用数组的队列中入队和出队操作的复杂度为O(1)


队列应用

  • CPU 调度,磁盘调度
  • 在两个进程之间异步传输数据时,使用队列进行同步。 例如:IO 缓冲区,管道,文件 IO 等
  • 实时系统中的中断处理。
  • 呼叫中心电话系统使用队列来保持人们按顺序呼叫他们