【发布时间】:2010-02-08 12:02:26
【问题描述】:
今天我读了一篇论文:
奥尼尔,梅丽莎 E.,“The Genuine Sieve of Eratosthenes", 函数式编程,已出版 剑桥大学出版社在线 2008 年 10 月 9 日 doi:10.1017/S0956796808007004.
描述了一种利用优先队列生成素数的算法:
sieve [] = []
sieve (x:xs) = x : sieve' xs (insertprime x xs PQ.empty)
where
insertprime p xs table = PQ.insert (p*p) (map (* p) xs) table
sieve' [] table = []
sieve' (x:xs) table
| nextComposite <= x = sieve' xs (adjust table)
| otherwise = x : sieve' xs (insertprime x xs table)
where
nextComposite = PQ.minKey table
adjust table
| n <= x = adjust (PQ.deleteMinAndInsert n' ns table)
| otherwise = table
where
(n, n':ns) = PQ.minKeyValue table
primes = sieve [2 .. ]
算法乍一看似乎是正确的,但我不明白一件事:
它使用的 PQ 如何处理重复的最低优先级?
我手工做了一些模拟,发现可能会导致错误。
如果有人能解释一下,我会很感激你的帮助!
【问题讨论】:
-
一篇非常漂亮的论文,顺便说一句。世界需要更多这样的人。
-
这很有趣。作者不遗余力地说明为什么一种算法不是埃拉托色尼的实际筛法,然后继续提出另一种不是的算法。关于数据结构有很多喋喋不休,实际上“正确”的实现使用简单的数组。实际算法的输出是这个数组 - 一个简单的表,所有组合都被划掉了。任何其他数据结构都可能有一些优势,人们可能会称其为“改进的埃拉托色尼筛法”之类的东西,但这并不是真正的交易。
-
@phkahler:使用优先级队列的唯一“优势”是它可以在 Haskell 中表达一个合理有效的解决方案。您可以通过在任何命令式语言中使用可扩展数组轻松恢复可扩展性的好处,就像 F# 所做的那样:fsharpnews.blogspot.com/2010/02/sieve-of-eratosthenes.html