c++隨機排序容器中的元素

在各類程序語言中都提供了將容器元素隨機排序的shuffle方法,c++也不例外。c++

不過c++將shuffle放在了<algorithm>中而不是像其餘語言同樣在random裏,同時c++17刪除了原先的random_shuffle新的程序應該使用c++11添加進去的std::shuffle。其中一個好處是新的函數在能夠自定義隨機數生成方法的同時保證了更好的安全性。算法

先來看下新函數的原型:安全

template< class RandomIt, class URBG >
void shuffle( RandomIt first, RandomIt last, URBG&& g );

其中firstlast指定須要隨機排序的範圍,g是一個「UniformRandomBitGenerator」,就是一個能夠產生規定範圍內的隨機數的可調用對象。dom

因此g能夠是std::random_device或者像std::default_random_engine這樣的隨機數引擎,也能夠是std::mt19937這樣的標準庫提供的隨機數生成器的對象,它們都在<random>中。函數

shuffle調用後目標容器內的元素排列順序會被隨機打亂,咱們看個例子。c++11

首先是兩個幫助函數,避免作一些重複勞動:code

// 幫助函數,打印vector的內容
template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v)
{
    os << "{ ";
    for (const auto &i: v) {
        os << i << ", ";
    }
    os << "}";

    return os;
}

// 幫助函數,生成一個符合UniformRandomBitGenerator要求的隨機數生成器;
// std::random_device雖然符合要求可是隻適合於生成seed及安全要求較高的場合,由於速度可能很慢。
// 因此咱們選擇std::mt19937算法,你能夠本身選擇其餘合適的算法
auto get_URBG()
{
    std::random_device rd;
    // 使用random_device生成seed
    std::mt19937 g(rd());

    return g;
}

而後咱們分別打亂一個std::vector<int>std::vector<std::string>容器內元素的排列順序:orm

// 隨機排序容器內元素,打印隨機排序前和隨機排序後的容器內容
template <typename T>
void shuffle_container(std::vector<T> &container)
{
    std::cout << "before shuffle: " << container << std::endl;
    std::shuffle(container.begin(), container.end(), get_URBG());
    std::cout << "after shuffle: " << container << std::endl;
}

int main()
{
    std::vector<int> ivec{1,2,3,4,5};
    shuffle_container(ivec);

    // 分割線
    std::cout << std::string(40, '-') << std::endl;

    std::vector<std::string> svec{"a", "b", "c", "d", "e", "f", "g"};
    shuffle_container(svec);
}

咱們編譯寫好的程序,而後運行:對象

能夠看到元素都已經被隨機排序了。blog

相關文章
相關標籤/搜索