Hàm std::next_permutation() trong header <algorithm> sắp xếp lại các phần tử thành hoán vị tiếp theo theo thứ tự từ điển (lexicographically). Trả về true nếu có hoán vị tiếp theo, false nếu đã ở hoán vị cuối cùng.
Cú pháp
bool next_permutation(BidirIt first, BidirIt last);
bool next_permutation(BidirIt first, BidirIt last, Compare comp);
Ví dụ: Chuỗi "DBAC"
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
string s = "DBAC";
cout << "Ban dau: " << s << endl;
for (int i = 0; i < 5; i++) {
bool has_next = next_permutation(s.begin(), s.end());
if (!has_next) {
cout << "Khong co hoan vi tiep theo" << endl;
break;
}
cout << "Tiep theo: " << s << endl;
}
}
Kết quả
Ban dau: DBAC Tiep theo: DBCA Tiep theo: DCAB Tiep theo: DCBA Khong co hoan vi tiep theo
Thuật toán đằng sau (C++ reference implementation)
- Tìm chỉ số
ilớn nhất sao chos[i] < s[i+1] - Nếu không tìm thấy → đã ở hoán vị cuối → trả về false
- Tìm chỉ số
jlớn nhất sao chos[j] > s[i] - Hoán đổi
s[i]vàs[j] - Đảo ngược dãy từ
i+1đến cuối
Ví dụ: Tạo tất cả hoán vị của "ABC"
#include <iostream>
#include <algorithm>
#include <string>
int main() {
string s = "ABC";
sort(s.begin(), s.end()); // Bắt đầu từ hoán vị nhỏ nhất
do {
cout << s << endl;
} while (next_permutation(s.begin(), s.end()));
}
Kết quả
ABC ACB BAC BCA CAB CBA
Lưu ý quan trọng
- Phạm vi phải hỗ trợ iterator ngẫu nhiên hoặc hai chiều (bidirectional)
- Để sinh tất cả hoán vị, hãy
sort()trước - Có phiên bản
prev_permutation()cho hoán vị trước - Độ phức tạp: O(n) cho mỗi lần gọi
Ứng dụng thực tế
- Giải bài toán du lịch thương nhân (TSP) brute-force
- Sinh test case cho thuật toán
- Thuật toán backtracking cần duyệt hoán vị