深入理解埃拉托色尼筛法与线性筛法

在计算素数的过程中,有两种经典的筛法:埃拉托色尼筛法(简称埃筛)线性筛法(简称线筛)。它们都是用于在给定的范围内找到所有素数的高效算法。本文将通过示例代码,详细对比这两种方法的原理、实现及其时间复杂度。

1. 埃拉托色尼筛法

原理概述

埃拉托色尼筛法的基本思想是通过不断标记合数来筛选出素数。具体来说,对于每一个素数 p,从 p*p 开始标记所有的倍数为非素数,因为更小的倍数已经在之前被标记过。

代码实现

以下是埃筛法的 C++ 实现:

#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    
    int n;
    cin >> n;
    
    vector<int> isPrime(n + 1, 1);  // 初始化所有数为素数
    isPrime[0] = isPrime[1] = 0;    // 0 和 1 不是素数

    for (int i = 2; i * i <= n; i++) {  // 从 2 开始到 sqrt(n)
        if (isPrime[i]) {  // 如果 i 是素数
            for (int j = i * i; j <= n; j += i) {  // 标记 i 的所有倍数为非素数
                isPrime[j] = 0;
            }
        }
    }

    // 输出所有素数
    for (int i = 0; i <= n; i++) {
        if (isPrime[i]) {
            cout << i << " ";
        }
    }
    
    return 0;
}
解析
  • 时间复杂度:埃拉托色尼筛法的时间复杂度为 O(nlog⁡log⁡n)。虽然对于每个素数 p,我们需要从 p*p开始标记所有倍数,但通过跳过非素数的倍数,算法仍然具有非常好的效率。

  • 空间复杂度:我们使用了一个大小为 n+1的数组来存储每个数是否是素数,因此空间复杂度为 O(n)。

输出示例

对于 n=30,输出结果为:

2 3 5 7 11 13 17 19 23 29
优缺点
  • 优点
    • 实现简单。
    • 适用于中等范围的素数筛选。
  • 缺点
    • 存在重复标记。例如,6 既是 2 的倍数也是 3 的倍数,因此会被多次标记。
    • 时间复杂度虽然是 O(nlog⁡log⁡n),但不是最优的。

2. 线性筛法

原理概述

线性筛法通过优化标记过程,确保每个合数只会被它的最小素数因数标记一次,从而避免了重复标记。与埃拉托色尼筛法不同,线性筛法可以严格保持线性时间复杂度 O(n)。

代码实现

以下是线性筛法的 C++ 实现:

#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    
    int n;
    cin >> n;
    
    vector<int> prime;
    vector<int> isPrime(n + 1, 1);  // 初始化所有数为素数
    isPrime[0] = isPrime[1] = 0;    // 0 和 1 不是素数

    for (int i = 2; i <= n; i++) {  // 从 2 遍历到 n
        if (isPrime[i]) {  // 如果 i 是素数
            prime.push_back(i);  // 将 i 加入素数列表
        }
        for (int j = 0; j < prime.size(); j++) {
            int p = prime[j];
            if (p * i > n) break;  // 如果 p * i 超过了 n,停止标记
            isPrime[p * i] = 0;    // 标记 p * i 为非素数
            if (i % p == 0) break; // 如果 i 能被 p 整除,停止标记
        }
    }

    // 输出所有素数
    for (int i = 0; i < prime.size(); i++) {
        cout << prime[i] << " ";
    }
    
    return 0;
}
解析
  • 时间复杂度:线性筛法的时间复杂度为 O(n),因为每个数 i 只会被其最小素数因数标记一次,避免了重复标记。

  • 空间复杂度:与埃拉托色尼筛法类似,空间复杂度也是 O(n)。

输出示例

对于 n=30,输出结果为:

2 3 5 7 11 13 17 19 23 29
优缺点
  • 优点
    • 时间复杂度为 O(n),更高效,特别是在处理大规模数据时效果显著。
    • 每个合数只被最小素数标记一次,避免了不必要的重复操作。
  • 缺点
    • 实现稍微复杂,需要维护素数列表并处理标记逻辑。

3. 对比分析 

 

4. 总结

  • 埃拉托色尼筛法是一个较为经典的素数筛选算法,适合中小规模的数据筛选,具有简单易懂的实现。
  • 线性筛法在进一步优化了筛选过程,能够在线性时间内完成素数筛选,特别适合大规模数据的处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值