C++에서 컨테이너의 요소를 무작위로 섞을 때 사용하는 대표적인 함수로 random_shuffle()과 shuffle()이 있습니다. 두 함수는 이름은 비슷하지만 내부 동작 방식과 권장 여부에 중요한 차이가 있습니다. 이번 글에서는 두 함수의 개념, 사용 예제, 그리고 핵심 차이점까지 자세히 살펴보겠습니다.
random_shuffle()이란?
random_shuffle()은 지정된 범위 [left, right) 내의 요소들을 무작위로 재배열하는 함수입니다. 각 요소의 위치를 임의로 선택된 다른 위치와 서로 교환(swap)하는 방식으로 동작합니다.
이 함수는 별도의 난수 생성기(random generator) 함수를 인자로 전달할 수 있습니다. 직접 만든 난수 생성기를 넘겨주면 그 기준으로 어떤 요소를 선택할지 결정하고, 아무것도 전달하지 않으면 함수 내부에 내장된 기본 난수 생성기를 사용합니다.
random_shuffle() 사용 예제
#include <bits/stdc++.h>
using namespace std;
int myRandomGenerator(int j) {
return rand() % j;
}
main() {
srand(unsigned(time(0)));
vector<int> arr;
for (int j = 1; j < 20; ++j) // 1부터 19까지 숫자를 생성해 벡터 arr에 추가
arr.push_back(j);
random_shuffle(arr.begin(), arr.end()); // 내장 난수 생성기로 셔플
cout << "arr elements:";
for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
cout << ' ' << *i;
cout << endl;
// 사용자 정의 난수 생성기(myRandomGenerator) 사용
random_shuffle(arr.begin(), arr.end(), myRandomGenerator);
cout << "arr elements:";
for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
cout << ' ' << *i;
cout << endl;
}실행 결과
arr elements: 5 14 15 6 3 16 13 12 10 2 4 1 17 9 18 11 7 8 19 arr elements: 8 10 5 6 14 1 15 3 19 16 13 18 7 9 4 12 11 17 2
위 예제에서 첫 번째 호출은 내장 난수 생성기를, 두 번째 호출은 사용자가 정의한 myRandomGenerator를 사용하여 같은 벡터를 서로 다른 방식으로 섞은 결과를 보여줍니다.
shuffle()이란?
shuffle() 역시 범위 [left, right) 내의 요소들을 무작위로 재배열하는 함수입니다. 다만 random_shuffle()과 달리, 반드시 균등 난수 생성기(uniform random number generator)를 인자로 전달해야 한다는 점이 특징입니다.
shuffle() 사용 예제
#include <bits/stdc++.h>
using namespace std;
main() {
vector<int> arr;
unsigned seed = 0;
for (int j = 1; j < 20; ++j) // 1부터 19까지 숫자를 생성해 벡터 arr에 추가
arr.push_back(j);
shuffle(arr.begin(), arr.end(), default_random_engine(seed));
cout << "arr elements:";
for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
cout << ' ' << *i;
cout << endl;
}실행 결과
arr elements: 19 7 5 6 12 4 13 3 1 17 11 14 18 2 8 15 9 10 16
예제에서는 C++11부터 표준 라이브러리에 포함된 default_random_engine을 시드(seed) 값과 함께 전달하여 셔플을 수행했습니다.
random_shuffle()과 shuffle()의 핵심 차이
두 함수의 가장 큰 차이는 난수 생성 방식입니다.
- random_shuffle(): 내부적으로
rand()함수를 사용해 무작위 인덱스를 생성합니다. 다만 균등 분포가 보장되지 않아 편향(bias)이 발생할 수 있습니다. - shuffle(): 균등 난수 생성기(uniform random number generator)를 사용하므로 모든 순열이 동일한 확률로 나타나는 통계적 균등성이 보장됩니다.
참고로, random_shuffle()에 균등 난수 생성기를 직접 전달하면 shuffle()과 유사한 결과를 얻을 수 있습니다.
어떤 것을 사용해야 할까?
random_shuffle()은 C++14에서 공식적으로 폐지(deprecated)되었고, C++17 표준부터는 완전히 제거되었습니다. 따라서 최신 C++ 프로젝트에서는 반드시 <algorithm> 헤더의 shuffle()과 <random> 헤더의 난수 엔진(예: mt19937, default_random_engine)을 함께 사용하는 것이 좋습니다. 이렇게 하면 이식성(portability)과 난수의 품질 모두 확보할 수 있습니다.