C++ 如何洗牌数组以使所有元素改变其位置

C++ 如何洗牌数组以使所有元素改变其位置,c++,random,shuffle,C++,Random,Shuffle,我需要洗牌一个数组,这样所有数组元素都应该改变它们的位置。 给定一个数组[0,1,2,3]可以得到[1,0,3,2]或[3,2,0,1],但不能得到[3,1,2,0](因为2保持不变)。 我猜想算法不是语言特定的,但在这种情况下,我需要在C++程序中使用它(并且我不能使用 STD::RealthyStuffle < /Cube >由于附加的要求)。 < P>它不会是非常随机的,但是你可以将所有元素旋转至少一个位置: std::rotate(v.begin(), v.begin() + (rand

我需要洗牌一个数组,这样所有数组元素都应该改变它们的位置。 给定一个数组
[0,1,2,3]
可以得到
[1,0,3,2]
[3,2,0,1]
,但不能得到
[3,1,2,0]
(因为
2
保持不变)。
我猜想算法不是语言特定的,但在这种情况下,我需要在C++程序中使用它(并且我不能使用<代码> STD::RealthyStuffle < /Cube >由于附加的要求)。

< P>它不会是非常随机的,但是你可以将所有元素旋转至少一个位置:

std::rotate(v.begin(), v.begin() + (rand() % v.size() - 1) + 1, v.end());
如果
v
在开始时是
{1,2,3,4,5,6,7,8,9}
,那么在旋转后它将是,例如:
{2,3,4,5,6,7,8,9,1}
,或
{3,4,5,6,7,8,9,1}
,等等

数组的所有元素都将改变位置

For each element e
    If there is an element to the left of e
        Select a random element r to the left of e
           swap r and e
这可以保证每个值都不在其开始的位置,但不能保证在存在重复值时每个值都会更改

注意,虽然简单,但这是有缺陷的。给定列表[0,1,2,3],此算法无法生成输出[1,0,3,2]。

这怎么办

  • 分配一个数组,该数组包含从0到arrayLength-1的数字
  • 洗牌
  • 如果数组中没有索引等于其值的元素,则继续执行步骤4;否则,重复步骤2
  • 使用无序数组值作为数组的索引

  • 我有一个想法,希望它适合你的申请。再有一个容器,此容器将 一个“映射(int,向量(int))”。键元素将显示索引,向量的第二个元素将保存已使用的值



    例如,对于第一个元素,您将使用rand函数查找应使用的数组元素。然后,如果数组的此元素已用于此索引,您将检查映射结构

    你有内存需求吗?您可以创建一个与第一个数组大小相同的新数组,然后将array1中的每个元素移动到array2中一个新的随机位置。如果已设置该值,请重试。另一种方法:从索引0开始,用随机的其他索引交换它。保留已交换的所有索引的列表。在列表上迭代,只交换未交换的项。最简单的方法,虽然完全不是随机的-将所有数组元素移动x个位置。在任何语言中都应该很容易做到,只需创建一个新数组,以偏移量复制第一个数组,然后在开始时复制其余的数组。为什么不能使用
    std::random_shuffle
    ?答案是否必须避免所有的
    ?所有的C++库?所有的图书馆?听起来你在寻找一个随机的疯子。有关算法,请参阅。此解决方案有问题吗?这不会洗牌数组。它给出了一个可预测的结果。简单正确的解决方案。我不认为有任何理由在解决方案中包含随机性,它与所述问题无关。即使结果是可预测的,原始问题中可接受的“解决方案”之一表明这是可以的<代码>[0,1,2,3]可以变成
    [3,1,2,0]
    。它改变每个元素的位置。你是从哪里得到关于洗牌的定义的,它是一种不能给出可预测结果的操作?很抱歉,关于“map(int,vector(int)),我不知道如何使用它“我相信这是Fisher-Yates shuffle的一个变种,被称为。这是一个非常简单的算法,如果没有人想到它,我会感到惊讶。”。我听说过费舍尔·耶茨,但以前没有听说过萨托洛。这并没有造成所有可能的混乱。考虑列表<代码> [01,1,3] 和上面允许的第一个输出:<代码> [1,03.2,2] < /代码>。此输出永远无法生成!请注意,在最后一步(即将交换3),列表看起来像
    [?,?,X,3]
    ,其中
    X
    不能为2,因为它在上一步中刚刚交换到
    位置之一。因此,
    X
    在最后一步之后以3结尾的唯一方法是,列表看起来像
    [?,?,3,X]
    ,X不能是2,因此无法生成排列。这种算法只产生了一小部分可能的精神错乱。@BeeOnRope:5年内,没有人注意到这一点。做得好!修正了。新算法只是一个(Fisher-Yates)洗牌-元素可以在开始的地方结束,违反了OPs要求。顺便说一句,据我所知,没有简单的直接产生混乱的算法——论文都是关于现存的算法写的。一种合理的概率方法就是如上所述生成一个洗牌,然后检查是否有任何元素留在原地,如果有则重试。这似乎很好,因为您可以将洗牌外包给
    std::random_shuffle
    ,洗牌似乎是最难的部分。这可以生成所有可能的允许输出,与公认的答案不同。