Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 两个列表中的随机对_C++_Arrays_Algorithm_Random_Permutation - Fatal编程技术网

C++ 两个列表中的随机对

C++ 两个列表中的随机对,c++,arrays,algorithm,random,permutation,C++,Arrays,Algorithm,Random,Permutation,我的问题类似于一个 我有两个列表:X包含n个元素,Y包含m个元素——假设它们包含nxm矩阵a的行和列索引。现在,我想在矩阵a中的k个随机位置写一些东西 我想到了两种解决方案: 从x中获取一个随机元素x,从y中获取一个随机元素y。检查某个元素是否已写入[x][y],如果未写入,则写入。但如果k接近m*n,我可以永远像这样射击。 用所有可能的索引组合创建一个m*n数组,将其洗牌,画出前k个元素并写入其中。但我在这里看到的问题是,如果n和m都非常大,那么新创建的n*m数组可能会很大,洗牌也可能需要一些

我的问题类似于一个

我有两个列表:X包含n个元素,Y包含m个元素——假设它们包含nxm矩阵a的行和列索引。现在,我想在矩阵a中的k个随机位置写一些东西

我想到了两种解决方案:

从x中获取一个随机元素x,从y中获取一个随机元素y。检查某个元素是否已写入[x][y],如果未写入,则写入。但如果k接近m*n,我可以永远像这样射击。 用所有可能的索引组合创建一个m*n数组,将其洗牌,画出前k个元素并写入其中。但我在这里看到的问题是,如果n和m都非常大,那么新创建的n*m数组可能会很大,洗牌也可能需要一些时间。 Karoly Horvath建议将两者结合起来。我想我必须选择阈值t和:

那么,关于如何选择t有什么建议吗


还有其他更好的方法我错过了吗?

由于Floyd的原因,不需要从一系列整数中进行替换就可以进行采样。你可以将所得的整数在[0,n*m ]中映射到C++函数[m ] int i {返回STD::MaMaGuiBiI/m,i %m;}。.

最佳方法取决于结果矩阵的填充程度。如果要填充一半以上的矩阵,则碰撞率(即获取已写入的随机点)将很高,并将导致循环次数远远超过您的期望

我不会生成所有的可能性,但我会使用列表列表来构建它。一个列表代表所有可能的X值,一个列表代表可能的Y值。我会初始化X列表,但不会初始化Y列表。 每次您第一次选择x值时,创建m个元素的字典或列表,然后删除您使用的元素。然后,下次选择x时,您将拥有m-1个元素,一旦x值用完元素,则将其从列表中删除,这样就不会再次选择。这样,您可以保证不再选择占用的空间,并且您不需要生成n*m个可能的选项。

您有n x m个元素,例如,10 x 20矩阵有200个元素。从200个元素中选择一个应该很容易。关键是,无论您做什么,您都可以将两个维度展平为一个,从而减少这部分问题

注:

使用floor divide和modulo操作从索引中获取行和列。 黑名单:将拾取的索引存储在一个集合中,以快速跳过已经写入的索引。 白名单:将尚未选取的索引存储在一个集合中。这是否优于黑名单取决于集合的完整程度。 为集合使用正确的容器类型可能很重要,它不必是std::set。对于黑名单,您只需要快速查找和快速插入,向量实际上可能工作得很好。对于白名单,您需要快速随机访问和快速删除,具有剩余索引的向量将是一个不错的选择。 根据情况,准备在两种方法之间切换。 对于一个NXM矩阵,可以考虑[0…n*M-1 ]矩阵元素的索引。

填充随机索引非常简单,只需生成一个介于0和n*m-1之间的随机数,这就是要填充的位置

随后执行此操作可能会有点棘手:

你可以测试你是否已经写了一些东西到一个位置并重新生成随机数;但是当你填充矩阵时,你将有更多的索引重新生成。 更好的解决方案是将所有索引放在n*m个元素的向量中。生成索引时,将其从列表中删除,然后下次生成一个介于0和n-1之间的随机索引 例如:

vector<int> indexVec;
for (i=0;i<n*m;i++)
    indexVec.push_back(i);
nrOfIndexes = n*m-1;
while (nrOfIndexes>1) 
{
   index = rand()% nrOfIndexes;
   processMatrixLocation(index); 
   indexVec.erase(indexVec.begin()+index);    
   nrOfIndexes--;
}
processMatrixLocation(indexVec[0]);

如果你在开始采样之前就知道k,这会有很大的不同。如果你知道,你可以得到k个样本或n*m-k,取较小的。或者你可以使用储层采样获得大k。
vector<int> indexVec;
for (i=0;i<n*m;i++)
    indexVec.push_back(i);
nrOfIndexes = n*m-1;
while (nrOfIndexes>1) 
{
   index = rand()% nrOfIndexes;
   processMatrixLocation(index); 
   indexVec.erase(indexVec.begin()+index);    
   nrOfIndexes--;
}
processMatrixLocation(indexVec[0]);