std::random_shuffle
#include <algorithm>
// Sử dụng bộ sinh số ngẫu nhiên mặc định
template <class RandomAccessIterator>
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last);
// Sử dụng hàm sinh số ngẫu nhiên tùy chỉnh
template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last,
RandomNumberGenerator& gen);
Xáo trộn (shuffle) ngẫu nhiên các phần tử trong một phạm vi (range) được chỉ định.
Tham số
first
- Random Access Iterator trỏ đến phần tử đầu tiên trong phạm vi cần xáo trộn.
last
- Random Access Iterator trỏ đến phần tử ngay sau phần tử cuối cùng trong phạm vi cần xáo trộn. Phạm vi là
[first, last)
.
gen
- Một hàm hoặc đối tượng hàm (generator) nhận một đối số nguyên dương
n
và trả về một số ngẫu nhiên trong khoảng[0, n)
. (Phiên bản 2)
Giá trị trả về
Không có giá trị trả về
Đặc điểm
- Phạm vi
[first, last)
là "nửa mở", không bao gồm phần tửlast
. random_shuffle()
thay đổi trực tiếp thứ tự các phần tử trong phạm vi gốc, không tạo ra một phạm vi mới.random_shuffle()
yêu cầu Random Access Iterator, cho phép truy cập ngẫu nhiên vào các phần tử.- Không sử dụng
random_shuffle()
trong code mới. Thay vào đó, hãy sử dụngstd::shuffle()
với bộ sinh số ngẫu nhiên chất lượng tốt từ thư viện<random>
. random_shuffle()
thường được sử dụng để:- Xáo trộn các phần tử trong một container (ví dụ: xáo trộn một bộ bài, tạo hoán vị ngẫu nhiên).
- Tạo thứ tự ngẫu nhiên cho các phần tử trong một mảng.
random_shuffle()
đã bị deprecated (khuyến cáo không nên dùng) trong C++14 và bị loại bỏ (removed) trong C++17. Thay vào đó, bạn nên sử dụng std::shuffle()
cùng với một bộ sinh số ngẫu nhiên (random number generator) như std::default_random_engine. Tuy nhiên, tôi vẫn sẽ giải thích về random_shuffle()
để bạn hiểu rõ hơn về lịch sử và cách các thuật toán trong <algorithm>
phát triển.
- Phiên bản
random_shuffle()
sử dụng bộ sinh số ngẫu nhiên mặc định (thường làstd::rand()
) có chất lượng ngẫu nhiên kém và phân bố không đều. - Phiên bản
random_shuffle()
với hàm sinh số ngẫu nhiên tự định nghĩa khó sử dụng đúng cách và dễ dẫn đến các lỗi tinh vi.
Ví dụ
Chỉ mang tính minh họa, không nên dùng trong code mới
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib> // For rand()
// Hàm sinh số ngẫu nhiên (không nên dùng cho code mới, thay bằng std::default_random_engine)
int myRandom(int i) {
return std::rand() % i;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8};
// Xáo trộn numbers sử dụng bộ sinh số ngẫu nhiên mặc định (không tốt)
std::random_shuffle(numbers.begin(), numbers.end());
std::cout << "numbers after random_shuffle (default): ";
for (int x : numbers) {
std::cout << x << " ";
}
std::cout << std::endl;
// Xáo trộn numbers sử dụng hàm sinh số ngẫu nhiên myRandom (không tốt)
std::random_shuffle(numbers.begin(), numbers.end(), myRandom);
std::cout << "numbers after random_shuffle (myRandom): ";
for (int x : numbers) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
Trong C++11 trở lên, bạn nên sử dụng std::shuffle()
cùng với một bộ sinh số ngẫu nhiên chất lượng tốt, ví dụ như std::default_random_engine hoặc std::mt19937 (Mersenne Twister).
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8};
// Tạo bộ sinh số ngẫu nhiên
std::random_device rd;
std::mt19937 gen(rd()); // Hoặc std::default_random_engine gen(rd());
// Xáo trộn numbers sử dụng std::shuffle() và bộ sinh số ngẫu nhiên gen
std::shuffle(numbers.begin(), numbers.end(), gen);
std::cout << "numbers after shuffle: ";
for (int x : numbers) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
Các hàm liên quan
rotate | Xoay (rotate) các phần tử trong một phạm vi (range) sang trái |
reverse | Đảo ngược thứ tự các phần tử trong một phạm vi (range) được chỉ định |
generate | Gán các giá trị được sinh ra bởi một hàm (hoặc đối tượng hàm) cho các phần tử trong một phạm vi (range) được chỉ định |
swap | Hoán đổi giá trị của hai đối tượng |