【问题标题】:Do you know a way to unsort an list or array?你知道取消排序列表或数组的方法吗?
【发布时间】:2012-02-14 13:52:58
【问题描述】:

我记得看到一个方法好像是冒泡排序,哪里可以取消排序项。

例如,我尝试使用 Random 类显示从 0 到 10 的随机项目。但我想这不是最好的选择。

所以,我猜想为 IEnumberable、List 或数组创建一个扩展,这可能是最好的方法。

【问题讨论】:

标签: c# algorithm sorting


【解决方案1】:

您正在寻找随机播放,随机重新排序的一个很好的例子是Fisher-Yates Shuffle

这是implementation by Jon Skeet in C#

【讨论】:

    【解决方案2】:

    看起来像冒泡排序的算法是:

    for i= 0:(len(x)-1):
        j = random(i,len(x)-1)
        swap(x[i],x[j])
    

    假设 random(a,b) 返回一个随机整数 c,使得 a

    而且,这个算法被称为“Fisher Yates Shuffle”。

    FWIW,您不能“真正”使用标准的内置随机数生成器对大数组进行洗牌。 21 项 shuffle 的熵为 65 位,而大多数 RNG 是 64 位或 32 位。

    【讨论】:

    • 如果您提到这是 Fisher-Yates shuffle 可能会有所帮助。
    【解决方案3】:

    这会给你一个从 0 到 10(包括 10)的随机值:

    int[] randomNumbers = Shuffle(Enumerable.Range(0, 11), new Random()).ToArray(); 
    
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random random)
    {
        T[] list = source.ToArray();
        int count = list.Length;
    
        while (count > 1)
        {
            int index = random.Next(count--);
            T temp = list[index];
            list[index] = list[count];
            list[count] = temp;
        }
        return list;
    }
    

    【讨论】:

    • 这不是'基本上'Fisher-Yates,它是从列表中随机选择的。它的共同点是公平和公正。它也是 O(n^2) 运行时。
    • 你到底为什么要以这种奇怪的方式随时间播种随机类?随机类自动使用当前时间播种自己。
    • 尼克当然是正确的;如果列表很大,这是非常低效的。
    • Fisher-Yates 是从一顶帽子中选择的数字,因为它们被移除了,所以剩下的数字也会缩小。顺便说一句,OP不需要Fisher-Yates,我只是在我认为应得的地方给予信任,它不值得-1。 OP 只想要从 0 到 10 的随机数。
    • Chuck,我认为你已经证明了你不应该在循环中创建 Random 实例。 10 个重复序列与 40 个重复序列,除非您实际测试 PRNG 的可重复结果,否则您不应该想要任何序列。您可能已经证明的第二件事是您的版本较慢,因为它在较少的迭代次数中超出了重复范围。
    【解决方案4】:

    你可以使用 linq...

    var result = Enumerable.Range(0,10).OrderBy( n=> Guid.NewGuid() )
    

    【讨论】:

    • 除了 LINQ 的 OrderBy/ThenBy 在底层使用 Quicksort 之外,给它 O( n log n ) 的性能(平均情况),更不用说需要额外的空间了。 “标准”洗牌算法是 O(n) 并且不需要额外的空间。
    • @L.B,OrderBy 是稳定的,它没有与列表中的 Sort 方法相同的缺点。对于一个小序列的快速一次性洗牌,使用 OrderBy 并不糟糕,但更好的算法肯定会更具可扩展性。
    • 这是一个非常糟糕的主意。 Guid 不保证是随机的,它们保证是唯一的。 使用 guid 制作唯一标识符;只用它们。 Guid 不是排序键。
    • 当然,这在 Guids 上是有效的。 “正确工作的正确工具”再次获胜。
    【解决方案5】:

    有趣的问题, 我建议离开工作linq:

    IEnumerable<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    Random rnd = new Random();
    list = list.Select(i => new { value = i, rank = rnd.Next(list.Count()) }).OrderBy(n => n.rank).Select(n => n.value);
    

    【讨论】:

      猜你喜欢
      • 2019-02-03
      • 2010-10-31
      • 2021-12-05
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多