洗牌堆<t>

时间:2015-11-11 02:06:26

标签: c# list generics stack shuffle

    public static void Shuffle<T> ( this Stack<T> stack )
    {
        List<T> list = stack.ToList ();
        list.Shuffle ();
        stack = list.ToStack ();
    }

    public static void Shuffle<T> ( this List<T> list )
    {
        for ( int i = 0; i < list.Count; i++ )
        {
            int num = Form1.rnd.Next ( list.Count );
            T temp = list[i];
            list[i] = list[num];
            list[num] = temp;
        }
    }

    public static Stack<T> ToStack<T> ( this List<T> list )
    {
        Stack<T> stack = new Stack<T> ();
        foreach ( T t in list )
            stack.Push ( t );

        return stack;
    }

以上是我试图改组通用堆栈。但是,尽管List Shuffle扩展方法有效,但Stack Shuffle不能按预期工作。就好像根本没有调用中间的Shuffle调用一样。相反,它仍然是相同的列表,没有洗牌。所以我认为问题出在ToStack函数中。有人可以解释我的错误吗?提前谢谢!

2 个答案:

答案 0 :(得分:5)

Shuffle方法(需要Stack<T>)按值获取堆栈参数。因此,当您调用stack = list.ToStack ();时,您正在更改方法本地的变量(stack)。

一个解决方案是按照您使用List<T> shuffle方法执行的操作:

public static Stack<T> Shuffle<T>(this Stack<T> stack)
{
    List<T> list = stack.ToList();
    list.Shuffle();
    return list.ToStack();
}

此方法将堆栈作为输入,以生成新的混洗堆栈。您可以像这样使用它:

Stack<int> stack = new Stack<int>();
for(int i = 0 ; i < 10 ; i++)
    stack.Push(i);

stack = stack.Shuffle();

答案 1 :(得分:2)

问题是你是将Stack<T>的新实例分配给局部变量,这意味着调用堆栈变量不会改变。

现在您可以在参数中添加ref,但我通常会尽量避免这样做。

以下是两种选择。

如果您想继续使用相同的参考,那么您可以这样做:

public static void Shuffle<T>(this Stack<T> stack)
{
    var values = stack.ToArray();
    stack.Clear();
    foreach (var value in values.OrderBy(x => rnd.Next()))
        stack.Push(value);
}

这非常简单,并且无需调用单独的方法进行随机播放。

或者,您可以返回Stack<T>的新实例。

public static Stack<T> Shuffle<T>(this Stack<T> stack)
{
    return new Stack<T>(stack.OrderBy(x => rnd.Next()));
}

这再次避免了调用单独的shuffle方法的需要。

这两种方法都使用.OrderBy(x => rnd.Next())来执行shuffle,这比交换索引要容易得多。