主要函数有:
- random_shuffle():采用均匀分布来随机移动元素。
random_shuffle函数模板的行为等效于:
template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last,
RandomNumberGenerator& gen)
{
iterator_traits<RandomAccessIterator>::difference_type i, n;
n = (last-first);
for (i=n-1; i>0; --i) {
swap (first[i],first[gen(i+1)]);
}
}
random_shuffle()有两个参数,第一个参数是指向序列首元素的迭代器,第二个参数则指向序列最后一个元素的下一个位置,上文的模板中第三个参数为自定义随机数发生器。实现打乱*[first,last)间元素顺序,随机生成一个新排列。
传统的随机数产生方法是使用ANSI C的函数rand(),然后格式化结果以便使结果落在指定的范围内。但是,使用这个方法至少有两个缺点。首先,做格式化时,结果常常是扭曲的,所以得不到正确的随机数(如某些数的出现频率要高于其他数)。其次,rand()只支持整型数,不能用它来产生随机字符、浮点数、字符串或数据库中的记录。
对于以上的两个问题, random_shuffle()算法给出了更好的解决方案,用这种算法可以产生不同类型的随机数。产生指定范围内的随机元素集的最佳方法是创建一个顺序序列(也就是向量或者内置数组),在这个顺序序列中含有指定范围的所有值,之后用random_shuffle()算法打乱元素排列顺序。
例子:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main(){
int a[] = {1, 2, 3, 4, 5};
float b[] = {1.1f, 2.1f, 3.1f, 4.1f, 5.1f};
char c[] = {'a', 'b', 'c', 'd', 'e'};
cout<< "原始数据a[] = ";
copy(a, a + 5, ostream_iterator<int>(cout, " "));
cout<< endl;
random_shuffle(a, a + 5);
cout<< "随机处理后: ";
copy(a, a + 5, ostream_iterator<int>(cout, " "));
cout<< endl;
cout<< "原始数据b[] = ";
copy(b, b + 5, ostream_iterator<int>(cout, " "));
cout<< endl;
random_shuffle(b, b + 5);
cout<< "随机处理后: ";
copy(b, b + 5, ostream_iterator<int>(cout, " "));
cout<< endl;
cout<< "原始数据c[] = ";
copy(c, c + 5, ostream_iterator<int>(cout, " "));
cout<< endl;
random_shuffle(c, c + 5);
cout<< "随机处理后: ";
copy(c, c + 5, ostream_iterator<int>(cout, " "));
return 0;
}
可以看出:利用random_shuffle实现了整型、浮点、字符序列的随机化,当然也可以是其他类型,前提是初始化序列必须已知。但是也有一个缺点:每次执行时产生的随机数序列是固定的,若想不固定,要用到random_shuffle 的第二个模板函数,例如:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <time.h>
using namespace std;
class MyRand{
public:
int operator()(int n){
srand(time(NULL));
return rand() % n;
}
};
int main(){
int a[] = {10, 21, 32, 43, 54, 65, 76, 87, 98};
vector<int> v(a, a + 9);
random_shuffle(v.begin(), v.end(), MyRand());
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
return 0;
}
程序每次执行时向量v元素序列都不同,关键是在一元函数MyRand类中,利用srand(time(NULL))使每次产生的随机数种子都不同。另外与上文讲的函数原型对比,"int operator()(int n)"中参数n不是向量v中的序列元素,而是[1,v. size()),即swap (first[i],first[gen(i+1)]);