c++隨機排序容器中的元素
阿新 • • 發佈:2019-02-04
範圍 engine 打印 程序 emp 分割 一個 cto 就是
在各種程序語言中都提供了將容器元素隨機排序的shuffle
方法,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 );
其中first
和last
指定需要隨機排序的範圍,g
是一個“UniformRandomBitGenerator”,就是一個可以產生規定範圍內的隨機數的可調用對象。
所以g
可以是std::random_device
或者像std::default_random_engine
這樣的隨機數引擎,也可以是std::mt19937
這樣的標準庫提供的隨機數生成器的對象,它們都在<random>
中。
shuffle
調用後目標容器內的元素排列順序會被隨機打亂,我們看個例子。
首先是兩個幫助函數,避免做一些重復勞動:
// 幫助函數,打印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>
容器內元素的排列順序:
// 隨機排序容器內元素,打印隨機排序前和隨機排序後的容器內容 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); }
我們編譯寫好的程序,然後運行:
可以看到元素都已經被隨機排序了。
c++隨機排序容器中的元素