【问题标题】:LINQ Quicksort is Unstable Except When CascadingLINQ 快速排序是不稳定的,除非在级联时
【发布时间】:2010-05-07 07:30:10
【问题描述】:

在“使用 C# 4.0 的 LINQ To Objects”(Tony Magennis)的第 64 页上,他指出 LINQ 的快速排序排序算法不稳定......

...虽然这可以简单地解决 将结果级联到 ThenBy 或 ThenByDescending 运算符。

嗯?为什么将不稳定的排序级联到另一个排序会修复结果?事实上,我会说这是不可能的。原始订单一旦通过不稳定的排序,就会丢失。我在这里错过了什么?

【问题讨论】:

    标签: linq sorting


    【解决方案1】:

    简单地说,他错了。 Linq OrderBy et al. 方法是 documented 执行稳定排序:

    此方法执行稳定排序;也就是说,如果两个元素的键相等,则保留元素的顺序。相反,不稳定的排序不会保留具有相同键的元素的顺序。

    【讨论】:

    • 因此,如果 Magennis 错了——排序是稳定的——那么他说它是快速排序显然是错误的。快速排序本质上是不稳定的。这就提出了一个问题:如果它不是快速排序,那么它是什么?
    【解决方案2】:

    不稳定的排序意味着x.OrderBy(...).OrderBy(...) 调用链只能根据最终标准可靠地排序。 x.OrderBy(...).ThenBy(...) 在应用新的排序顺序时显式捕获先前排序顺序的知识。我相信它通过调用IOrderedEnumerable<TElement>.CreateOrderedEnumerable<TKey> 来做到这一点,尽管我不是 100% 确定这一点。

    编辑:为了清楚起见,当我说“捕获知识......”时,我并不是说第一个 OrderBy 执行排序,而第二个知道它做了什么。请记住,OrderBy 返回一个IOrderedEnumerable<T>,在有人尝试使用这些元素之前它根本不会执行任何工作。在这种情况下,它永远不会执行排序,因为ThenBy 使用OrderBy 如何排序的知识,构建了一个全新的排序器,该排序器以预期的方式和一步。

    有人指出 Magennis 在不稳定排序的事情上是错误的。但是,上述描述仍然有效。

    【讨论】:

    • 啊,我明白了...他说你应该使用x.OrderBy(a => a.LastName).OrderBy(a => a.FirstName) 而不是x.OrderBy(a => a.LastName).ThenBy(a => a.FirstName)。这比我的回答更有意义:)
    • 排序的“稳定性”是一个 comp-sci 概念,与“捕获先前排序的知识”无关。似乎 Magennis 不应该使用“不稳定排序”这个名称。
    • 好吧,如果 LINQ 使用不稳定排序,那么“不稳定排序”是正确的指示符。当然,他可能是错的,但假设他不是,我已经修改了答案,也许可以消除混乱。
    【解决方案3】:

    他的意思是如果这样做,说orderby LastName,那么任何具有相同姓氏的人都会以不可预知的顺序排序。因此,如果您将其与 orderby LastName, FirstName 结合使用,您可以再次使顺序可预测(当然,姓氏相同的人除外)。

    至少,我会这么认为。

    【讨论】:

      猜你喜欢
      • 2017-05-13
      • 2015-06-02
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      • 2019-12-21
      • 2010-11-28
      • 2016-06-23
      • 2010-09-16
      相关资源
      最近更新 更多