Arraylist Shuffle算法使用一个键

Arraylist Shuffle algorithm using a key

我如何在 C# ArrayList 中编写一个可逆随机播放算法,它使用一个键来随机播放并且可以反转到原始状态?

您可以使用KeyValuePair。您可以在以下网站上获得详细说明:http://www.dotnetperls.com/shuffle

但是如果你想反转它,我建议使用数据表。在第一列中,您可以使用原始排序顺序(可能是整数),在第二列中,您可以创建随机数。在第三列中,您可以拥有需要排序的值。然后使用按第二列排序进行随机播放,然后按第一列排序将其还原。

这里有一个简单的方法,只需要你存储你的"key",并且不改变洗牌算法。

使用哪种随机播放算法并不重要,只要你能重现它,这意味着如果你使用相同的密钥或种子,并且运行两次随机播放算法,它将完全相同地随机播放两次都是这样。

如果您可以使用密钥或随机播放算法的种子来做到这一点,那么您就可以开始了。

为了反转它,你所要做的就是打乱一个整数数组,打乱之前数组中的值对应于每个元素的索引。洗牌后,使用与上面相同的键或种子,您现在有一个洗牌副本,其中每个值都是未洗牌数组中原始位置的索引。

举个例子

假设一个包含 4 个整数的数组,值为 0 到 3(索引 0 处的元素值为 0,索引 1 处的元素值为 1,依此类推)。

将这个打乱,得到这个数组:3,1,2,0。

这意味着打乱后的数组的第一个元素曾经位于索引 3,第二个元素位于索引 1,第三个位于索引 2,第四个位于索引 0。

    private class myItem
    {
        public Int32 ID { get; set; }
        public Int32 Rand { get; set; }
        public String Value { get; set; }

    }

    private void Main(object sender, EventArgs e)
    {

        string[] array = new string[] { "alpha", "beta", "gamma", "delta" };
        List<myItem> myArray = addKeys(array);//adds keys to array required for randomization and reversing
        string[] randomarray = randomize(myArray);
        string[] reversedarray = reverse(myArray);

    }
    private List<myItem> addKeys(string[] array)
    {
        Random random = new Random();
        List<myItem> myArr = new List<myItem>();
        for (int i = 0; i < array.Length; i++)
        {
            myArr.Add(new myItem { ID = i, Rand = random.Next(), Value = array[i] });

        }
        return myArr;
    }
    private string[] randomize(List<myItem> myArray)
    {
        return (from item in myArray
                         orderby item.Rand
                         select item.Value).ToArray();
    }
    private string[] reverse(List<myItem> myArray)
    {
        return (from item in myArray
                         orderby item.ID
                         select item.Value).ToArray();
    }

Shuffling一个数组是通过多次交换数组内部的元素来完成的。

如果你拿一个数组,交换元素,然后再次交换它们,但以你最初交换它们的相反顺序,你会得到原来的数组。

这些洗牌位置可以从PRNGPseudorandom number generator)生成。对于给定的 seedPNRG 将始终生成相同的数字:那将是您的 "key".

下面是一些使用该想法的代码(Fisher Yates 用于随机播放):

public static void Shuffle(ArrayList list, int seed, bool reverse = false)  
{           
    Random rng = new Random(seed); 
    List<Tuple<int, int>> swaps = new List<Tuple<int, int>>();
    int n = list.Count;  

    //prepare swapping positions 
    while (n > 1) {  
        n--;  
        int k = rng.Next(n + 1);  
        swaps.Add(new Tuple<int, int>(k, n));
    }

    //reverse if needed
    if(reverse)
        swaps.Reverse();

    //swap the items
    foreach(Tuple<int, int> swap in swaps)
    {       
        object value = list[swap.Item1];  
        list[swap.Item1] = list[swap.Item2];  
        list[swap.Item2] = value;
    }
}

用法:

ArrayList a = new ArrayList();
int key = 2742;

Shuffle(a, key);
Shuffle(a, key, true);

请注意,如果您不希望密钥是一个整数,而是一个字符串,您可以使用完全相同的方法,但整数使用 "somekey".GetHashCode()