【问题标题】:The Genuine Sieve of Eratosthenes -- algorithm used to generate prime numbers埃拉托色尼的真正筛子——用于生成素数的算法
【发布时间】: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

标签: algorithm haskell


【解决方案1】:

论文中提到了正在使用的优先级队列:

鉴于这些需求,优先队列 是一个有吸引力的选择,特别是因为这种数据结构本身支持多个 具有相同优先级的项目(按任意顺序出列)。

由于重复条目在算法中并不是真正有用,因此必须对其进行特殊处理。

删除最小组合的adjust 函数不断调整优先级队列,直到可以确定最小元素的所有重复项都被删除:

adjust table
    | n <= x = adjust (PQ.deleteMinAndInsert n_ ns table)
    | otherwise = table
    where ...

如果当前的第一个元素 (n) 小到足以被删除,adjust 再次调用自身以检查剩余队列中的下一个元素。只有当没有剩余的小元素时才会停止递归。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多