C++ 使用除两个值之外的唯一整数填充向量的更快方法?C++;

C++ 使用除两个值之外的唯一整数填充向量的更快方法?C++;,c++,optimization,random,vector,C++,Optimization,Random,Vector,我不能在这里发布我所有的程序,只是片段。我会回答任何问题 我拥有的: for (int i = 0; i < _iterations; i++) { players.clear(); int y = 0; do{ // _pop_size = 20 int rand_i = static_cast<int>(rand_double(0, _pop_size));

我不能在这里发布我所有的程序,只是片段。我会回答任何问题

我拥有的

for (int i = 0; i < _iterations; i++)
    {
        players.clear();
        int y = 0;
        do{
            // _pop_size = 20
            int rand_i = static_cast<int>(rand_double(0, _pop_size));
            if (rand_i != 3 && rand_i != 6){
             // verify if the ID already exists in vector
                if (std::find(players.begin(), players.end(), rand_i) == players.end()){
                    players.push_back(rand_i);
                    ++y;
                }
            }
          } while (y < _group_size - 1);
   // ...
   // ...
   // ...
   // ...
    double rand_double(int min, int max) const
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<double> dist(min, max);

    return dist(mt);
}
1) 我有一个有20个ID的向量,像这样[0,1,2,3,4,5,6…19]

2) 我选择两个ID,例如3号和6号

我需要什么

for (int i = 0; i < _iterations; i++)
    {
        players.clear();
        int y = 0;
        do{
            // _pop_size = 20
            int rand_i = static_cast<int>(rand_double(0, _pop_size));
            if (rand_i != 3 && rand_i != 6){
             // verify if the ID already exists in vector
                if (std::find(players.begin(), players.end(), rand_i) == players.end()){
                    players.push_back(rand_i);
                    ++y;
                }
            }
          } while (y < _group_size - 1);
   // ...
   // ...
   // ...
   // ...
    double rand_double(int min, int max) const
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<double> dist(min, max);

    return dist(mt);
}
1) 生成大小为N-1的向量,其中N=5。这个向量不应该包含数字3和数字6,只包含剩余的ID,并且不要重复它们。 例如:新向量=[7,2,19,4]。是的,只有4个项目,因为第5个是数字3或数字6,它们将与新创建的组一起玩,因此1+4=5(N)

我的问题

for (int i = 0; i < _iterations; i++)
    {
        players.clear();
        int y = 0;
        do{
            // _pop_size = 20
            int rand_i = static_cast<int>(rand_double(0, _pop_size));
            if (rand_i != 3 && rand_i != 6){
             // verify if the ID already exists in vector
                if (std::find(players.begin(), players.end(), rand_i) == players.end()){
                    players.push_back(rand_i);
                    ++y;
                }
            }
          } while (y < _group_size - 1);
   // ...
   // ...
   // ...
   // ...
    double rand_double(int min, int max) const
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<double> dist(min, max);

    return dist(mt);
}

1) 我需要这样做一百万次。它非常慢。我相信这部分代码是最重的,因为我删除了那部分,没有它程序运行得非常快

我的问题

for (int i = 0; i < _iterations; i++)
    {
        players.clear();
        int y = 0;
        do{
            // _pop_size = 20
            int rand_i = static_cast<int>(rand_double(0, _pop_size));
            if (rand_i != 3 && rand_i != 6){
             // verify if the ID already exists in vector
                if (std::find(players.begin(), players.end(), rand_i) == players.end()){
                    players.push_back(rand_i);
                    ++y;
                }
            }
          } while (y < _group_size - 1);
   // ...
   // ...
   // ...
   // ...
    double rand_double(int min, int max) const
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<double> dist(min, max);

    return dist(mt);
}
1) 下面是我的代码,do-while循环,我能以某种方式优化它吗?也许我需要使用另一种结构或更智能的方法来生成它

代码

for (int i = 0; i < _iterations; i++)
    {
        players.clear();
        int y = 0;
        do{
            // _pop_size = 20
            int rand_i = static_cast<int>(rand_double(0, _pop_size));
            if (rand_i != 3 && rand_i != 6){
             // verify if the ID already exists in vector
                if (std::find(players.begin(), players.end(), rand_i) == players.end()){
                    players.push_back(rand_i);
                    ++y;
                }
            }
          } while (y < _group_size - 1);
   // ...
   // ...
   // ...
   // ...
    double rand_double(int min, int max) const
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<double> dist(min, max);

    return dist(mt);
}
for(int i=0;i<\u迭代;i++)
{
玩家。清除();
int y=0;
做{
//_pop_size=20
int rand_i=静态(rand_double(0,_pop_size));
if(rand_i!=3&&rand_i!=6){
//验证vector中是否已存在该ID
if(std::find(players.begin()、players.end()、rand_i)=players.end()){
玩家。推回(rand_i);
++y;
}
}
}而(y<组大小-1);
// ...
// ...
// ...
// ...
rand_double()函数

for (int i = 0; i < _iterations; i++)
    {
        players.clear();
        int y = 0;
        do{
            // _pop_size = 20
            int rand_i = static_cast<int>(rand_double(0, _pop_size));
            if (rand_i != 3 && rand_i != 6){
             // verify if the ID already exists in vector
                if (std::find(players.begin(), players.end(), rand_i) == players.end()){
                    players.push_back(rand_i);
                    ++y;
                }
            }
          } while (y < _group_size - 1);
   // ...
   // ...
   // ...
   // ...
    double rand_double(int min, int max) const
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<double> dist(min, max);

    return dist(mt);
}
double rand\u double(int-min,int-max)常数
{
std::随机_装置rd;
标准:mt19937 mt(rd());
标准:均匀实分布距离(最小值、最大值);
返回区(mt);
}

这个答案部分是收集评论,部分是证明一个观点

我们的目标是尽可能多地退出处理循环。首先是重复重新初始化随机数生成器。随机数生成器应该设置一次,然后重复使用,因此重新初始化是个坏主意。很好的摆脱

下一步是找到一种更快的方法来拒绝已知的元素。当前的方法是通过未排序的向量进行线性搜索。插入速度很快,因为如果调整大小,推回只会减慢速度,但向量中的项目越多,最坏情况下的搜索时间就越长。std::set是一个有序列表,具有非常快的查找速度,有些hat慢速插入。如果列表较短,请使用vector。如果列表较长(\u group\u size>100),请使用集合

下面是一个长列表示例:

#include <iostream>
#include <set>
#include <vector>
#include <random>
#include <functional>
#include <chrono>
#include <algorithm>

using namespace std::chrono; // I know, but the lines were ridiculously long

// remove random number generator init from processing loop.
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<int> dist(0, 1000000);
// replace function with a bind.
auto rand_int = std::bind(dist, mt);

// test function
int main()
{
    int y;
    int _group_size = 10000; // loop 10000 times
    std::set<int> tempplayers;
    std::vector<int> players;


    auto start = high_resolution_clock::now(); // get start time
    // with vector
    do
    {
        // _pop_size = 20
        int rand_i = rand_int();
        if (rand_i != 3 && rand_i != 6)
        { //using vector: Linear search.
            if (std::find(players.begin(), players.end(), rand_i) == players.end())
            {
                players.push_back(rand_i);
                ++y;
            } // verify if the ID already exists in vector
        }
    } while (y < _group_size - 1);
    auto t1 = duration_cast<nanoseconds>(high_resolution_clock::now() - start).count();
    // Calculate elapsed time

    std::cout << "Time (ns) with vector: " << t1 << std::endl;

    // reset
    players.clear();
    y = 0;

    // run again with a set instead of a vector
    start = high_resolution_clock::now();
    do
    {
        // _pop_size = 20
        int rand_i = rand_int();
        if (rand_i != 3 && rand_i != 6)
        { //using set. Not sure exactly what search it is. Probably a tree.
            if (tempplayers.find(rand_i) == tempplayers.end())
            {
                tempplayers.insert(rand_i);
                //players.push_back(rand_i);
                ++y;
            }
        }
    } while (y < _group_size - 1);
    // copy set into vector for comfortable use.
    std::copy(tempplayers.begin(), 
              tempplayers.end(), 
              std::back_inserter(players));
    //
    auto t2 = duration_cast<nanoseconds>(high_resolution_clock::now() - start).count();
    std::cout << "Time (ns) with set: " << t2 << std::endl;
    if (t2 > 0)
    {
        std::cout << "Set is " << t1/ t2 << " times faster"<< std::endl;
    }
}

注意:我在Windows上运行,默认的刻度分辨率非常糟糕。

更好的方法是使用简单的数组而不是向量。 因为我知道组的大小,所以我只需创建一个大小为x的数组,并将值添加到其中。要检查这些值是否已经在数组中,我使用了一个简单的for循环

当一个向量为下一个数字和一个数组分配内存时会发生什么情况?不,当我这样做时,他已经为这些数字分配了内存:

int array[4];

一个测试花了我96秒,在我换成阵列后,同一个测试只花了26秒。

“我需要这样做100万次。”问:你“需要做多少次?”?更具体地说,你能从循环中得到什么???只需分析你的逻辑,找到你不需要重复的东西,然后把它从循环中带出来。@πάνταῥεῖ 这将很快被击落。不要迁移垃圾。rand_double函数:你不必每次都重新给生成器播种。将函数中除返回距离(mt)之外的所有内容取出并将其放在全局空间中,使其初始化一次。然后查看std::bind,因为您可以
auto rand\u double=std::bind(dist,mt);
并完全放弃该函数。接下来,为什么要创建随机双精度,然后将其转换为int?为什么不首先使用?在进行转换时,类似比例的双精度将截断为同一个整数,因此,如果这样做,你就完蛋了,如果不这样做,你就完蛋了。我的结果不同:[Time(ns)with vector:174136500][Time(ns)使用set:160125800][set快1倍]。但是如果我将group_大小设置为100000,set快6倍。从技术上讲,您是正确的。我会将您的答案标记为正确的。谢谢您的课程。