主要函数有:

  • 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;
}

c++ STL随机算法:random_shuffle()详解_随机算法

可以看出:利用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;
}

c++ STL随机算法:random_shuffle()详解_STL_02

程序每次执行时向量v元素序列都不同,关键是在一元函数MyRand类中,利用srand(time(NULL))使每次产生的随机数种子都不同。另外与上文讲的函数原型对比,"int operator()(int n)"中参数n不是向量v中的序列元素,而是[1,v. size()),即swap (first[i],first[gen(i+1)]);