深入理解埃拉托色尼筛法与线性筛法
创作时间:
作者:
@小白创作中心
深入理解埃拉托色尼筛法与线性筛法
引用
CSDN
1.
https://m.blog.csdn.net/2202_75569688/article/details/142813349
在计算素数的过程中,有两种经典的筛法:埃拉托色尼筛法(简称埃筛)和线性筛法(简称线筛)。它们都是用于在给定的范围内找到所有素数的高效算法。本文将通过示例代码,详细对比这两种方法的原理、实现及其时间复杂度。
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(nloglogn)。虽然对于每个素数 p,我们需要从 p*p开始标记所有倍数,但通过跳过非素数的倍数,算法仍然具有非常好的效率。
- 空间复杂度:我们使用了一个大小为 n+1的数组来存储每个数是否是素数,因此空间复杂度为 O(n)。
输出示例
对于 n=30,输出结果为:
2 3 5 7 11 13 17 19 23 29
优缺点
优点:
实现简单。
适用于中等范围的素数筛选。
缺点:
存在重复标记。例如,6 既是 2 的倍数也是 3 的倍数,因此会被多次标记。
时间复杂度虽然是 O(nloglogn),但不是最优的。
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. 总结
- 埃拉托色尼筛法是一个较为经典的素数筛选算法,适合中小规模的数据筛选,具有简单易懂的实现。
- 线性筛法在进一步优化了筛选过程,能够在线性时间内完成素数筛选,特别适合大规模数据的处理。
热门推荐
如何在银行办理个人外汇储蓄账户的外汇风险管理
无偿献血者专属权益:用血报销与优先用血政策详解
如何实施DNSSEC
武汉老年卡能免费乘地铁吗?
协同发展,医保互认手持一张医保卡,京津冀看病更方便
国有企业如何打造”职能共享中心“?
这一年,我们不断提升创新实力
国家地方共建具身智能机器人创新中心揭牌 加速推动产品落地
中国农历何以成为“最懂农业”的时间算法
公立医院绩效考核系统如何促进医生职业发展?
选择合适的数据序列化格式
污水处理厂的建设与设计考虑
东风、长安迎重组的背后
东风与长安合并 全球汽车行业格局迎来巨震
税务申报服务流程详解:6步流程与5大注意事项
鹿茸与阿胶:对比分析两者补血效果的优劣
科创板股票投资:股票指数与投资策略
憋气可以练肺活量吗?提升肺活量的科学方法
春季诺如病毒肠胃炎如何防?
出现幻听时的自救指南
产生幻听是什么原因
现金流折现率表怎么看的出来
人的腰椎有几节
板书设计方案
三国志战略版张角阵容搭配攻略:三种流派详解
创办洋务运动可以实现国家繁荣,为何李鸿章参与的洋务运动失败?
洋务运动的历史地位:一次失败的封建统治者自救运动
腮帮子痒警惕四种病
脉搏68次/分钟,正常吗?专家这样说
快速傅里叶变换(FFT)生成的频率、幅度具体求解过程