我需要随机填充一个给定数量的特定值的矩阵。 (出于某种原因,我有一个C
2D数组。我找到的简单解决方案是将2D数组解释为一维数组:(请忽略硬编码常量和临时随机对象):
int m[10][10] = {};
std::fill_n(&m[0][0], 24, -1);
std::shuffle(&m[0][0], &m[0][0] + 100, std::mt19937{std::random_device{}()});
但这似乎是有争议的,因为它是否是未定义的行为:
Is it legal to access a bidimensional array as if it where a one-dimensional one?
May I treat a 2D array as a contiguous 1D array?
要点是,即使基础数据保证连续而没有行之间的填充,索引方案或在第一行之外递增&m[0][0]
int*
指针也是无效的。
所以我正在寻找另一种安全方法。有没有一种简单的方法可以在不创建一维数组然后将其复制到矩阵中的情况下填充然后重新排列2D数组?
注意:矩阵的其余部分都是0
,因此不需要保留这些单元格。
答案 0 :(得分:3)
假设您的2d数组的维度为 m X n ,它已初始化,并且您希望进行就地随机随机播放。
为此修改Durstenfeld variant of the Fisher-Yates Shuffling algorithm非常容易。以下是伪代码:
for i = m * n - 1 downto 1
j = random integer in the range [0, i] (both inclusive)
swap(a[i / n][i % n], a[j / n][j % n])
这基本上是原始算法,将数组视为1d。无论何时选择索引 i 和 j ,在对其执行操作之前,都会为每个转换为行+列。
答案 1 :(得分:1)
是否有一种简单的方法可以在不创建一维数组的情况下填充二维数组然后进行随机播放
不确定。假设你填充了阵列,为了改变它,为什么不随机生成i1
,i2
,j1
,j2
其中i和j是限制的行和列。现在交换这些指数的值。这样说 0.5 x no.of.rows x no.of.cols ,这只是一个非常粗略的数字。基本上随意随意随意添加它。任何小于10^8
的东西都应该没问题。
如果您担心生成重复对(对于较大的矩阵,这不应该是一个问题),您可以维护std::set<pair<int, int> >
来存储生成的索引。每当您生成i
和j
时,请检查{i, j}
是否存在。如果是,请重新生成它。
答案 2 :(得分:1)
您可以在整数(1-D)索引和(i,j)对之间选择双射函数,因此这将是将矩阵视为1-D数组的方法。这被称为编号方案&#39;。
类似的东西:
oneDindex(rowIndex,colIndex)=colIndex*rowCount+rowIndex;
逆变换
rowIndex=oneDIndex % rowCount
colIndex=oneDIndex / rowCount;
因此,您需要在[0,rowCount * colCount]中随机选择两个要交换的1D索引,通过逆变换获取它们(rowIndex,colIndex)并进行交换。重复直到满意为止。