时间:2019-03-08 标签:c#pass-by-referenceFisher-YatesShuffler

标签 c# algorithm pass-by-reference shuffle

我正在尝试使用 Fisher-Yates 算法来打乱一堆元素。我在通过引用传递堆栈时遇到问题。下面的代码给出了错误“迭代器不能有 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;
        }
    }
}

最佳答案

How do I get the algorithm to act on the actual stack that gets passed in?

不需要需要 refStack<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;
    }
}

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

foreach (var item in Doshuffle.Shuffle(gameDeck)) 
{ 
   System.Console.WriteLine(item.cardName); 
}

还要小心使用 Random - 你可能想传入它。此时你可以使用 Jon Skeet's Shuffle implementation而不是您自己的 - 重用比重新发明更好。

最终编辑:

看起来你只是想洗牌你的 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);
    }
}

现在你可以这样做:

gameStack.Shuffle();

关于时间:2019-03-08 标签:c#pass-by-referenceFisher-YatesShuffler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7143100/

相关文章:

c# - 如何配置 NLog 以写入数据库?

c# - 用 C# 编写可升级的软件及其升级

java - Dijkstra algorithm alternatives - graph, bus routes 中的最短路径

c# - 文件哈希算法代码c#

arrays - 如何在 swift 函数中返回一个 inout(引用)?

C++ if/else if 语句不起作用

c# - 没有 add in linq 语法的定义?

c# - 列表框项目中的多行 C#

performance - 有限排序/过滤算法

java - Power/Mockito 忽略引用更新