2.2.Cấu trúc dữ liệu hàng đợi
Hàng đợi là một cấu trúc dữ liệu hữu ích trong lập trình. Nó tương tự như hàng đợi mua vé bên ngoài rạp chiếu phim, nơi người đầu tiên vào hàng đợi là người đầu tiên lấy được vé.
Hàng đợi tuân theo quy tắc First In First Out (FIFO) - mục nào vào trước thì mục đó ra trước.
Biểu diễn FIFO của hàng đợi
Trong hình ảnh trên, vì 1 được giữ trong hàng đợi trước 2, nên nó cũng là mục đầu tiên được xóa khỏi hàng đợi. Nó tuân theo quy tắc FIFO.
Theo thuật ngữ lập trình, việc đưa các mục vào hàng đợi được gọi là enqueue, và việc xóa các mục khỏi hàng đợi được gọi là dequeue.
Chúng ta có thể triển khai hàng đợi trong bất kỳ ngôn ngữ lập trình nào như C, C++, Java, Python hoặc C#, nhưng thông số kỹ thuật thì khá giống nhau.
2.2.1. Các hoạt động cơ bản của hàng đợi
Hàng đợi là một đối tượng (một cấu trúc dữ liệu trừu tượng - ADT) cho phép các hoạt động sau:
2.2.2. Hoạt động của hàng đợi
Các hoạt động của hàng đợi hoạt động như sau:
2.2.3.Hoạt động xếp hàng
2.2.4.Hoạt động Dequeue
Các hoạt động Enqueue và Dequeue
2.2.5. Triển khai hàng đợi trong Python, Java, C và C++
Chúng ta thường sử dụng mảng để triển khai hàng đợi trong Java và C/++. Trong trường hợp của Python, chúng ta sử dụng danh sách.
#Python
# Queue implementation in Python
class Queue():
def __init__(self, k):
self.k = k
self.queue = [None] * k
self.head = self.tail = -1
# Insert an element into the queue
def enqueue(self, data):
if (self.tail == self.k - 1):
print("The queue is full\n")
elif (self.head == -1):
self.head = 0
self.tail = 0
self.queue[self.tail] = data
else:
self.tail = self.tail + 1
self.queue[self.tail] = data
# Delete an element from the queue
def dequeue(self):
if (self.head == -1):
print("The queue is empty\n")
elif (self.head == self.tail):
temp = self.queue[self.head]
self.head = -1
self.tail = -1
return temp
else:
temp = self.queue[self.head]
self.head = self.head + 1
return temp
def printQueue(self):
if(self.head == -1):
print("No element in the queue")
else:
for i in range(self.head, self.tail + 1):
print(self.queue[i], end=" ")
print()
# Your Queue object will be instantiated and called as such:
obj = Queue(5)
obj.enqueue(1)
obj.enqueue(2)
obj.enqueue(3)
obj.enqueue(4)
obj.enqueue(5)
print("Initial queue")
obj.printQueue()
obj.dequeue()
print("After removing an element from the queue")
obj.printQueue()
#Java
// 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 (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 because the 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();
}
}
#C
// Queue implementation in C
#include <stdio.h>
#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 because the 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");
}
#C++
// Queue implementation in C++
#include <iostream>
#define SIZE 5
using namespace std;
class Queue {
private:
int items[SIZE], front, rear;
public:
Queue() {
front = -1;
rear = -1;
}
bool isFull() {
if (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 because the 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;
}
2.2.6. Giới hạn của hàng đợi
Như bạn có thể thấy trong hình ảnh bên dưới, sau một chút thêm vào và loại bỏ hàng đợi, kích thước của hàng đợi đã được giảm bớt.
Giới hạn của hàng đợi
Và chúng ta chỉ có thể thêm các chỉ mục 0 và 1 khi hàng đợi được thiết lập lại (khi tất cả các phần tử đã được loại khỏi hàng đợi).
Sau khi REAR đạt đến chỉ mục cuối cùng, nếu chúng ta có thể lưu trữ các phần tử bổ sung trong các khoảng trống (0 và 1), chúng ta có thể sử dụng các khoảng trống. Điều này được thực hiện bằng một hàng đợi đã sửa đổi được gọi là hàng đợi vòng tròn.
2.2.7. Phân tích độ phức tạp
Độ phức tạp của các thao tác enqueue và dequeue trong hàng đợi sử dụng một mảng là O(1). Nếu bạn sử dụng pop(N) trong mã python, thì độ phức tạp có thể là O(n) tùy thuộc vào vị trí của mục cần được bật lên.
2.2.8. Ứng dụng của hàng đợi
ĐỌC THÊM VỀ Cấu trúc dữ liệu và thuật toán -CHƯƠNG II CẤU TRÚC DỮ LIỆU tại đây :
1.Cấu trúc dữ liệu và thuật toán -CHƯƠNG I :Giới thiệu DSA
2.Cấu trúc dữ liệu và thuật toán -CHƯƠNG I :Giới thiệu DSA (tiếp theo...)
3.Cấu trúc dữ liệu và thuật toán -CHƯƠNG I :Giới thiệu DSA (Phần 3...)
4.Cấu trúc dữ liệu và thuật toán -CHƯƠNG II CẤU TRÚC DỮ LIỆU-NGĂN XẾP