c#传递参考Fisher-Yates Shuffler

Oje*_*jen 1 c# algorithm shuffle pass-by-reference

我试图使用Fisher-Yates算法来混淆一堆元素.我无法通过引用传入堆栈.下面的代码给出了错误"Iterators不能有ref或out参数".如何让算法对传入的实际堆栈起作用?

谢谢.

代码如下.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
public static class Doshuffle
{
    public static IEnumerable<T> Shuffle<T>(ref Stack<T> source)
    {

        Random rng = new Random();
        T[] elements = source.ToArray();
        source.Clear();
        // Note i > 0 to avoid final pointless iteration
        for (int i = elements.Length - 1; i > 0; i--)
        {
            // Swap element "i" with a random earlier element it (or itself)
            int swapIndex = rng.Next(i + 1);
            T tmp = elements[i];
            elements[i] = elements[swapIndex];
            elements[swapIndex] = tmp;
        }
        // Lazily yield (avoiding aliasing issues etc)
        foreach (T element in elements)
        {
            source.Push(element);
            yield return element;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

}

Bro*_*ass 7

如何让算法对传入的实际堆栈起作用?

没有需要ref,因为这里的参数Stack<T>是引用类型,你是不是要重新分配基准本身.

默认情况下,引用按值传递,但该值(引用)指向堆上的同一个对象,换句话说,您有两个引用指向同一个对象,这很好 - 所有操作都将在原始Stack<T>对象上执行.

编辑:

根据您的评论,我建议您重新设计,不要修改原始Stack<T>的麻烦:

public static IEnumerable<T> Shuffle<T>(Stack<T> source)
{
    Random rng = new Random();
    T[] elements = source.ToArray();
    // Note i > 0 to avoid final pointless iteration
    for (int i = elements.Length - 1; i > 0; i--)
    {
        // Swap element "i" with a random earlier element it (or itself)
        int swapIndex = rng.Next(i + 1);
        T tmp = elements[i];
        elements[i] = elements[swapIndex];
        elements[swapIndex] = tmp;
    }
    // Lazily yield (avoiding aliasing issues etc)
    foreach (T element in elements)
    {
        yield return element;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以像这样使用它:

foreach (var item in Doshuffle.Shuffle(gameDeck)) 
{ 
   System.Console.WriteLine(item.cardName); 
}
Run Code Online (Sandbox Code Playgroud)

另外要小心使用Random- 你可能想要传入它.此时你可以使用Jon Skeet的Shuffle实现而不是你自己的实现 - 重用比重新创建更好.

最终编辑:

看起来你只想把自己洗牌Stack<T>- 使用扩展方法代替:

public static void Shuffle<T>(this Stack<T> source)
{
    Random rng = new Random();
    T[] elements = source.ToArray();
    source.Clear();
    // Note i > 0 to avoid final pointless iteration
    for (int i = elements.Length - 1; i > 0; i--)
    {
        // Swap element "i" with a random earlier element it (or itself)
        int swapIndex = rng.Next(i + 1);
        T tmp = elements[i];
        elements[i] = elements[swapIndex];
        elements[swapIndex] = tmp;
    }
    foreach (T element in elements)
    {
        source.Push(element);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

gameStack.Shuffle();
Run Code Online (Sandbox Code Playgroud)