关于惰性求值的澄清及其效率

27 浏览
0 Comments

关于惰性求值的澄清及其效率

我在Real World Haskell上看到了以下句子:

惰性求值有一些神奇的效果。假设我们想要找到未排序列表中最小的k个元素。在传统的语言中,显而易见的方法是对列表进行排序并取前k个元素,但这很耗费时间。为了提高效率,我们将编写一个特殊的函数,一次性获取这些值,它将需要执行一些适度复杂的簿记。在Haskell中,排序-然后-获取方法实际上表现良好:惰性确保列表只会被排序到足以找到k个最小元素。

他们还为此提供了一种代码实现:

minima k xs = take k (sort xs)

但是,这真的是这样吗?我认为,即使在Haskell中,也应该对列表进行完整排序才能取出k个元素。(想象一下最小的数字在列表末尾的情况)。我在这里漏掉了什​​么吗?

admin 更改状态以发布 2023年5月20日
0
0 Comments

(这里只是把我的评论作为回答) 遍历整个列表并不等于对其进行排序。假设进行快速排序,其中您围绕枢轴分割列表,然后递归地对列表的左右两半进行排序。如果您只问左半部分中的元素,则无需对右半部分进行排序。可以递归地应用这个论点。因此,如果您在排序后从长度为n的列表中获取 k个元素,则复杂度为O(n + klog k),而不是 O(n log n)。正如@MoFu所指出的那样,Heinrich在这里有一篇很好的博客文章。

0