🧾 C++ STL • Queue

QUEUE
HÀNG ĐỢI TRONG C++

Bài giảng được soạn lại theo kiểu trực quan: hiểu cơ chế FIFO, biết các hàm thành viên, viết được chương trình mô phỏng hàng đợi và áp dụng vào BFS.

FIFOVào trước ra trước
front()Lấy phần tử đầu
push()Thêm vào cuối hàng
BFSỨng dụng quan trọng
1

Khái niệm Queue

Queue là gì?

Queue hay hàng đợi là cấu trúc dữ liệu lưu trữ các phần tử theo cơ chế FIFO: First In, First Out, nghĩa là phần tử vào trước sẽ được lấy ra trước.

Người đến trướcĐứng đầu hàngĐược phục vụ trước

Ví dụ thực tế: xếp hàng mua vé, xếp hàng khám bệnh, hàng đợi in tài liệu.

Cú pháp khai báo

Trong C++, queue thuộc thư viện chuẩn STL. Có thể dùng bằng cách khai báo:

#include <bits/stdc++.h>
using namespace std;

queue<int> q;
queue<string> dsTen;
Ghi nhớ: Queue không cho truy cập ngẫu nhiên như mảng/vector. Ta chỉ làm việc chủ yếu với đầu hàng và cuối hàng.

Mô hình hoạt động

push: thêm cuốifront: xem đầupop: bỏ đầu

Giả sử lần lượt đưa vào queue các số 1, 2, 3, 4, 5. Khi lấy ra, thứ tự nhận được cũng là 1, 2, 3, 4, 5.

2

Các hàm thành viên của queue

HàmÝ nghĩaĐộ phức tạpVí dụ
size()Trả về số lượng phần tử hiện có trong queue.O(1)q.size()
empty()Trả về true nếu queue rỗng, ngược lại false.O(1)q.empty()
push(x)Đẩy phần tử x vào cuối hàng đợi.O(1)q.push(5)
pop()Loại bỏ phần tử ở đầu hàng đợi.O(1)q.pop()
front()Truy cập phần tử ở đầu hàng đợi.O(1)q.front()
back()Truy cập phần tử ở cuối hàng đợi.O(1)q.back()
swap(q2)Hoán đổi nội dung của hai queue cùng kiểu.O(n)q.swap(q2)
Lưu ý quan trọng: Trước khi dùng front(), back() hoặc pop(), nên kiểm tra queue có rỗng hay không bằng empty().
3

Ví dụ code cơ bản

Thêm và lấy phần tử

#include <bits/stdc++.h>
using namespace std;

int main(){
    queue<int> q;

    for(int i = 1; i <= 5; i++){
        q.push(i);
    }

    cout << q.front() << "\n"; // 1
    cout << q.back()  << "\n"; // 5

    q.pop();
    cout << q.front() << "\n"; // 2
}

Duyệt và in queue

Queue không duyệt bằng chỉ số. Muốn in toàn bộ, ta lấy dần phần tử đầu rồi xóa đi.

while(!q.empty()){
    cout << q.front() << " ";
    q.pop();
}
Nếu cần giữ nguyên queue ban đầu, hãy sao chép sang queue phụ rồi duyệt trên bản sao.

Mô phỏng chuyển phần tử đầu về cuối

int x = q.front();
q.pop();
q.push(x);

Đây là thao tác dùng trong bài CHUYENDOI: chuyển phần tử đầu tiên về cuối hàng đợi.

4

Ứng dụng của queue

Mô phỏng xếp hàng

Dùng queue để mô phỏng người đến trước được xử lý trước: mua vé, khám bệnh, xử lý yêu cầu.

Duyệt BFS

Queue là cấu trúc dữ liệu cốt lõi của thuật toán BFS để tìm đường đi ngắn nhất theo số cạnh trên đồ thị không trọng số.

Sinh trạng thái

Dùng queue để sinh dần các trạng thái theo từng lớp, ví dụ tìm số may mắn nhỏ nhất chia hết cho K.

Khung BFS cơ bản

queue<int> q;
vector<int> dist(n + 1, -1);

q.push(s);
dist[s] = 0;

while(!q.empty()){
    int u = q.front();
    q.pop();

    for(int v : adj[u]){
        if(dist[v] == -1){
            dist[v] = dist[u] + 1;
            q.push(v);
        }
    }
}
5

Bảng tổng quan bài tập

BàiTên bàiKỹ năng chínhMức độ
1CHUYENDOIMô phỏng xoay queueDễ
2MUAVEMô phỏng hàng đợiTrung bình
3BFSQueue + đường đi ngắn nhấtTrung bình
4DANBOQueue xử lý nhómTrung bình
5LUCKYNUMBFS trên số dưKhá
6

Nội dung bài tập

Câu 1. Chuyển đổi dãy số

CHUYENDOI.*

Sói có một dãy số. Mỗi lần chuyển đổi, phần tử đầu tiên của dãy được đưa về cuối dãy. Sau K lần chuyển đổi, hãy in ra dãy số mới.

Dữ liệu vàoN, K và N số nguyên dương.
Kết quảDãy sau khi biến đổi.
Giới hạn1 ≤ N ≤ 104, 1 ≤ K ≤ 109

Input

5 3
1 2 3 4 5

Output

4 5 1 2 3
Gợi ý nhanh: Chỉ cần xoay K mod N lần, hoặc dùng công thức bắt đầu từ vị trí K mod N.

Câu 2. Mua vé

MUAVE.*

Có N người xếp hàng. Người có chiều cao ≤ K được miễn phí và rời hàng. Người có chiều cao > K bị đưa về cuối hàng. Nhân viên kiểm tra M lần. Hãy đếm số lần mỗi người được kiểm tra.

Dữ liệu vàoN, K, M và N chiều cao.
Kết quảN số là số lần mỗi người được kiểm tra.
Giới hạn1 ≤ N, K ≤ 103, 1 ≤ M ≤ 104

Input

6 3 7
1 4 6 2 3 5

Output

1 2 1 1 1 1
Gợi ý nhanh: Lưu cặp (chiều cao, chỉ số ban đầu) trong queue. Mỗi lần lấy đầu queue để xử lý.

Câu 3. Tìm đường đi ngắn nhất

BFS.*

Cho đồ thị vô hướng gồm N thành phố và M con đường. Tìm số cạnh ít nhất để đi từ S đến T. Nếu không có đường đi, in -1.

Dữ liệu vàoN, M, S, T và M cạnh u v.
Kết quảĐộ dài đường đi ngắn nhất.
Giới hạnN ≤ 1000, M ≤ 2000

Input

5 5 1 4
1 2
2 3
3 5
5 4
2 4

Output

2
Gợi ý nhanh: Dùng BFS từ S, mảng dist lưu khoảng cách. Đáp án là dist[T].

Câu 4. Đàn bò

DANBO.*

Ban đầu có N con bò. Nếu một nhóm có thể chia thành hai nhóm sao cho chênh lệch đúng bằng K thì tiếp tục chia. Nếu không chia được thì nhóm dừng lại. Hỏi cuối cùng có bao nhiêu nhóm bò?

Dữ liệu vàoHai số N và K.
Kết quảSố nhóm bò sau cùng.
Giới hạn1 ≤ N ≤ 109, 1 ≤ K ≤ 103

Input

6 2

Output

3
Gợi ý nhanh: Một nhóm x chia được nếu x > K và x - K chẵn. Khi đó chia thành (x-K)/2 và (x+K)/2. Dùng queue để xử lý các nhóm còn có thể chia.

Câu 5. Số may mắn nhỏ nhất

LUCKYNUM.*

Tìm số nhỏ nhất chỉ gồm các chữ số 6 và 8, có không quá 200 chữ số, chia hết cho K. Nếu không tồn tại, in -1.

Dữ liệu vàoMột số nguyên K.
Kết quảSố may mắn nhỏ nhất hoặc -1.
Giới hạn1 < K < 104

Input

43

Output

86
Gợi ý nhanh: BFS trên số dư. Từ số dư r, thêm chữ số 6 hoặc 8 tạo số dư mới: (r*10+d)%K. Lưu cha để truy vết số.
style> body { user-select: none; }