队列是编程中有用的数据结构。它类似于电影院大厅外面的售票队列,在该队列中,第一个进入队列的人是第一个获得票的人。
队列遵循先进先出(FIFO)规则-先进入的项目也是先进入的项目。
在上图中,由于1在2之前保留在队列中,因此它也是第一个从队列中删除的队列。它遵循FIFO规则。
用编程术语来说,将项目放入队列称为“入队”,而将项目从队列中删除则称为“出队”。
我们可以使用任何编程语言(例如C,C++,Java, Python或C#)来实现队列,但是规范几乎是相同的。
队列的基本操作
队列是一个对象,或更具体地说是一个允许执行以下操作的抽象数据结构(ADT):
- 入队 :将元素添加到队列的末尾
- 出队 :从队列的前面删除一个元素
- IsEmpty :检查队列是否为空
- IsFull :检查队列是否已满
- 窥视 :获取队列最前面的值而不删除它
队列工作
队列操作如下:
- 两个指针FRONT和REAR
- 前跟踪队列的第一个元素
- REAR跟踪队列的最后一个元素
- 最初,将FRONT和REAR的值设置为-1
入队操作
- 检查队列是否已满
- 对于第一个元素,将FRONT的值设置为0
- 将REAR指数提高1
- 在REAR指向的位置添加新元素
出队操作
- 检查队列是否为空
- 返回FRONT指向的值
- 将FRONT指数提高1
- 对于最后一个元素,将FRONT和REAR的值重置为-1
Python,Java,C和C++中的队列实现
最常见的队列实现是使用数组,但是也可以使用列表来实现。
Python
爪哇
C
C +
# Queue implementation in Python
class Queue:
def __init__(self):
self.queue = []
# Add an element
def enqueue(self, item):
self.queue.append(item)
# Remove an element
def dequeue(self):
if len(self.queue) < 1:
return None
return self.queue.pop(0)
# Display the queue
def display(self):
print(self.queue)
def size(self):
return len(self.queue)
q = Queue()
q.enqueue(1)
q.enqueue(2)
q.enqueue(3)
q.enqueue(4)
q.enqueue(5)
q.display()
q.dequeue()
print("After removing an element")
q.display()
// Queue implementation in Java
public class Queue {
int SIZE = 5;
int items[] = new int[SIZE];
int front, rear;
Queue() {
front = -1;
rear = -1;
}
boolean isFull() {
if (front == 0 && rear == SIZE - 1) {
return true;
}
return false;
}
boolean isEmpty() {
if (front == -1)
return true;
else
return false;
}
void enQueue(int element) {
if (isFull()) {
System.out.println("Queue is full");
} else {
if (front == -1)
front = 0;
rear++;
items[rear] = element;
System.out.println("Inserted " + element);
}
}
int deQueue() {
int element;
if (isEmpty()) {
System.out.println("Queue is empty");
return (-1);
} else {
element = items[front];
if (front >= rear) {
front = -1;
rear = -1;
} /* Q has only one element, so we reset the queue after deleting it. */
else {
front++;
}
System.out.println("Deleted -> " + element);
return (element);
}
}
void display() {
/* Function to display elements of Queue */
int i;
if (isEmpty()) {
System.out.println("Empty Queue");
} else {
System.out.println("\nFront index-> " + front);
System.out.println("Items -> ");
for (i = front; i <= rear; i++)
System.out.print(items[i] + " ");
System.out.println("\nRear index-> " + rear);
}
}
public static void main(String[] args) {
Queue q = new Queue();
// deQueue is not possible on empty queue
q.deQueue();
// enQueue 5 elements
q.enQueue(1);
q.enQueue(2);
q.enQueue(3);
q.enQueue(4);
q.enQueue(5);
// 6th element can't be added to queue because queue is full
q.enQueue(6);
q.display();
// deQueue removes element entered first i.e. 1
q.deQueue();
// Now we have just 4 elements
q.display();
}
}
// Queue implementation in C
#include
#define SIZE 5
void enQueue(int);
void deQueue();
void display();
int items[SIZE], front = -1, rear = -1;
int main() {
//deQueue is not possible on empty queue
deQueue();
//enQueue 5 elements
enQueue(1);
enQueue(2);
enQueue(3);
enQueue(4);
enQueue(5);
//6th element can't be added to queue because queue is full
enQueue(6);
display();
//deQueue removes element entered first i.e. 1
deQueue();
//Now we have just 4 elements
display();
return 0;
}
void enQueue(int value) {
if (rear == SIZE - 1)
printf("\nQueue is Full!!");
else {
if (front == -1)
front = 0;
rear++;
items[rear] = value;
printf("\nInserted -> %d", value);
}
}
void deQueue() {
if (front == -1)
printf("\nQueue is Empty!!");
else {
printf("\nDeleted : %d", items[front]);
front++;
if (front > rear)
front = rear = -1;
}
}
// Function to print the queue
void display() {
if (rear == -1)
printf("\nQueue is Empty!!!");
else {
int i;
printf("\nQueue elements are:\n");
for (i = front; i <= rear; i++)
printf("%d ", items[i]);
}
printf("\n");
}
// Queue implementation in C++
#include
#define SIZE 5
using namespace std;
class Queue {
private:
int items[SIZE], front, rear;
public:
Queue() {
front = -1;
rear = -1;
}
bool isFull() {
if (front == 0 && rear == SIZE - 1) {
return true;
}
return false;
}
bool isEmpty() {
if (front == -1)
return true;
else
return false;
}
void enQueue(int element) {
if (isFull()) {
cout << "Queue is full";
} else {
if (front == -1) front = 0;
rear++;
items[rear] = element;
cout << endl
<< "Inserted " << element << endl;
}
}
int deQueue() {
int element;
if (isEmpty()) {
cout << "Queue is empty" << endl;
return (-1);
} else {
element = items[front];
if (front >= rear) {
front = -1;
rear = -1;
} /* Q has only one element, so we reset the queue after deleting it. */
else {
front++;
}
cout << endl
<< "Deleted -> " << element << endl;
return (element);
}
}
void display() {
/* Function to display elements of Queue */
int i;
if (isEmpty()) {
cout << endl
<< "Empty Queue" << endl;
} else {
cout << endl
<< "Front index-> " << front;
cout << endl
<< "Items -> ";
for (i = front; i <= rear; i++)
cout << items[i] << " ";
cout << endl
<< "Rear index-> " << rear << endl;
}
}
};
int main() {
Queue q;
//deQueue is not possible on empty queue
q.deQueue();
//enQueue 5 elements
q.enQueue(1);
q.enQueue(2);
q.enQueue(3);
q.enQueue(4);
q.enQueue(5);
//6th element can't be added to queue because queue is full
q.enQueue(6);
q.display();
//deQueue removes element entered first i.e. 1
q.deQueue();
//Now we have just 4 elements
q.display();
return 0;
}
队列限制
如您在下图中所看到的,在进行一些入队和出队后,队列的大小已减小。
只有当所有元素都已出队后,才能在重置队列后使用索引0和1。
在REAR到达最后一个索引之后,如果我们可以在多余的空间(0和1)中存储额外的元素,则可以利用这些空白。这是通过称为循环队列的修改队列来实现的。
复杂度分析
使用数组的队列中入队和出队操作的复杂度为O(1)
。
队列数据结构的应用
- CPU调度,磁盘调度
- 在两个进程之间异步传输数据时。该队列用于同步。例如:IO缓冲区,管道,文件IO等
- 实时系统中的中断处理。
- 呼叫中心电话系统使用队列来使人们按顺序呼叫
推荐读物
- 队列类型
- 循环队列数据结构
- 双端队列数据结构
- 优先队列数据结构
- Java中的队列实现