【问题标题】:How to generate a list of shuffled arrays from a given array?如何从给定的数组生成洗牌数组的列表?
【发布时间】:2021-11-03 22:45:43
【问题描述】:

我在互联网上寻找这个问题,发现我可以使用<algorithm> 标头中的 random_shuffle 函数。我的以下代码:

void Localization::generate_population(){
    int* ptr = new int[size];
    for(int i{}; i < size; ++i) ptr[i] = i;

    for(int i{}; i < size; ++i) {
        std::random_shuffle(ptr, ptr + size);
        population[i] = ptr;
    }
}

这是我的类函数,它在构造函数中自动调用。我运行了这个程序,最终得到了相同的洗牌数组。网上告诉我,我忘记在程序开头添加std::srand(std::time(0)),所以我就这样做了:

我删除了一些代码以使其更易于阅读。希望它仍然可以理解。

int main(int argc, char **argv){
    std::srand(std::time(0));

    Localization* gps = new Localization(array_here);
    delete gps;
}

但是,当我构建并运行我的程序时,我得到了类似的结果:

[ INFO] [1630975155.983523195]: 0: [2, 4, 6, 0, 5, 1, 3]
[ INFO] [1630975155.983979451]: 1: [2, 4, 6, 0, 5, 1, 3]
[ INFO] [1630975155.983990418]: 2: [2, 4, 6, 0, 5, 1, 3]
[ INFO] [1630975155.983996142]: 3: [2, 4, 6, 0, 5, 1, 3]
[ INFO] [1630975155.984001312]: 4: [2, 4, 6, 0, 5, 1, 3]
[ INFO] [1630975155.984006477]: 5: [2, 4, 6, 0, 5, 1, 3]
[ INFO] [1630975155.984013677]: 6: [2, 4, 6, 0, 5, 1, 3]

不完全确定std::srand(std::time(0)) 是如何工作的,但可能是因为for 循环运行得太快,std::srand(std::time(0)) 无法生效。在我的情况下,有没有更好的方法来洗牌?

编辑的代码(工作但不确定是否有效):

#include <iostream>
#include <algorithm>
#include <iterator>
#include <random>

int main(){
    int size {5};
    int** a2d = new int*[size]; 
    int* ptr = new int[size];
    for(int i{}; i < size; ++i) ptr[i] = i;

    std::random_device rd;
    std::default_random_engine dre{ rd() }; 
    for(int i{}; i < size; ++i){
        int* another = new int[size];
        std::copy(ptr, ptr + size, another);
        std::shuffle(another, another + size, dre);
        a2d[i] = another;
        std::copy(another, another + size, ptr);
    }
    delete ptr;

    for(int i{}; i < size; ++i){
        printf("%d: %d, %d, %d, %d, %d\n", i, a2d[i][0], a2d[i][1], a2d[i][2], a2d[i][3], a2d[i][4]);
    }
}

输出:

0: 3, 2, 4, 0, 1
1: 0, 1, 3, 4, 2
2: 4, 3, 1, 2, 0
3: 3, 2, 0, 1, 4
4: 0, 4, 2, 1, 3

【问题讨论】:

  • random_shuffle 已被弃用。请改用shuffle
  • std::time 的分辨率为 1 秒,因此如果您在同一秒内多次运行程序,您将获得相同的种子,因此您会获得相同的“随机”结果。 srandrand 糟透了(并且通过扩展,std::shuffle 已弃用)。使用新的 &lt;random&gt; 功能 (link)。
  • 所有population 的元素都指向同一个指针...使用std::vector 将允许拥有真正的副本(无需手动处理内存)。
  • 你可能会避免使用newLocalization gps(array_here);main 中就足够了。 std::vector/std::array 用于不同的号码列表。

标签: c++ arrays random shuffle


【解决方案1】:

正如@cigien 评论的那样,random_shuffle 已被弃用。您可以使用标准的“shuffle”函数来随机播放给定容器的所有元素。

std::random_device rd;
std::default_random_engine dre{ rd() }; // seed RNG

std::shuffle(std::begin(myContainer), std::end(myContainer), dre);

【讨论】:

  • 请注意,虽然这种方法肯定比问题中的方法更好,但对于 std::random_device 实际上是随机的并没有严格的要求。在某些平台上,每次执行都可以是相同的字节序列。 "std::random_device 可以根据实现定义的伪随机数引擎来实现,如果非确定性源(例如硬件设备)对实现不可用。在这种情况下,每个 std::random_device对象可能会生成相同的数字序列。” 但大多数时候,它是不确定的。
  • @spitconsumer 你好,我编辑了我的帖子并使用了你的方法,但为了满足我的需求,可能以一种非常低效的方式。我想不出更好的方法来做到这一点,并且可能不会切换到向量,因为我最终将不得不经历另一年的艰苦调试程序,只是为了这个“相当简单”的任务。有什么建议吗?
  • 谁说过向量?您可以使用带有指针的标准算法。有一个指向要排序的十个整数数组的指针吗? std::sort(myPointer, myPointer+10); 是的,别担心,它很有效。标准容器和函数基本上是你能得到的最好的。我只能假设,您只能使用不可移植的东西变得更好。使用可用的东西。不要重新发明轮子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
  • 2015-04-15
  • 2019-08-18
  • 1970-01-01
  • 2013-06-28
相关资源
最近更新 更多