一、算法简介
埃拉托斯特尼筛法(埃氏筛) 是最经典、最高效的素数筛选算法之一,专门用于快速筛选出 2~n 范围内的所有素数。相比于普通暴力枚举判断素数的方法,埃氏筛通过倍数标记法剔除合数,极大降低了时间复杂度。
普通素数判断时间复杂度:O(n\\sqrt{n})
埃氏筛算法时间复杂度:O(n\\log\\log n)
该算法核心思想:素数的所有倍数一定是合数,只需遍历每个素数,将其所有倍数标记为合数,最终未被标记的数即为素数。
二、算法核心原理
-
数组初始化:定义布尔数组,默认将所有数字标记为素数;
-
特殊值剔除:0 和 1 不属于素数,手动标记为非素数;
-
遍历筛选:从 2 开始遍历,若当前数是素数,则将其所有平方及以上的倍数标记为合数(优化点:从 i\*i 开始遍历,避免重复筛选);
-
结果输出:遍历数组,所有标记为 true 的数值即为范围内的素数。
重点优化说明:常规筛法会从 2\*i 开始标记倍数,会产生重复筛选;从 i\*i 开始筛选,可大幅减少循环次数,提升运行效率。
cpp
#include <stdio.h>
#include <stdbool.h>
#define MAXN 1000000
// 埃氏筛法筛选素数,全局数组默认初始化为false
bool is_prime[MAXN];
/**
* @brief 埃氏筛核心函数,筛选2~n范围内的所有素数
* @param n 筛选上限
*/
void eratosthenes_sieve(int n){
数组:默认所有数为素数
t i=0;i<=n;i++){
is_prime[i]=true;
// 0和1不是素数,单独标记
is_prime[0]=is_prime[1]=false;
// 遍历2~sqrt(n),筛选素数
or(int i=2;i*i<=n;i++){
如果当前数是素数,标记其所有倍数为合数
if(is_prime[i]){
从i*i开始标记,避免重复筛选
for (int j = i * i; j <= n; j += i) {
is_prime[j] = false;
}
}
}
int main(){
置素数筛选上限
n=100;
// 调用筛法函数
atosthenes_sieve(n);
// 格式化输出所有素数
rintf("小于等于%d的素数有:\n", n);
boo = true; // 控制逗号格式,避免末尾多余逗号
for (int i = 2; i <= n; i++) {
if (is_prime[i]) {
if (!first) {
printf(", ");
}
printf("%d", i);
first = false;
}
}
("\n");
turn 0;
}
re printfl first p er int // 设 }
// // f
} for(in // 初始化
四、代码详细解析
1. 头文件与宏定义
-
#include <stdio.h>:提供输入输出打印功能; -
#include <stdbool.h>:支持 C 语言布尔类型(true/false); -
#define MAXN 1000000:定义数组最大容量,支持百万级数据筛选,可根据需求修改。
2. 全局标记数组
bool is_prime[MAXN] 作为素数标记数组:
-
true:代表当前下标数值为素数;
-
false:代表当前下标数值为合数/非素数。
3. 筛法核心函数
-
数组初始化:将 0~n 所有数值默认标记为素数;
-
特殊处理:0、1 不是素数,强制标记为 false;
-
外层循环:只遍历到 \\sqrt{n},减少循环次数(合数一定存在小于自身的因数);
-
内层循环:对每个素数 i,标记其所有大于等于i\*i 的倍数为合数。
4. 主函数格式化输出
通过 first 布尔变量控制输出格式,素数之间用逗号分隔,解决传统输出末尾多余逗号的问题,输出结果更整洁规范。
五、运行结果展示
代码默认筛选 100 以内所有素数,运行输出结果如下:
cpp
小于等于100的素数有:
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
六、算法优缺点分析
✅ 优点
-
筛选效率极高,远优于暴力枚举法,适合大批量素数筛选;
-
逻辑清晰、代码简洁,易于理解和二次修改;
-
通过 i\*i 起始优化,规避了重复筛选问题。
❌ 缺点
-
需要开辟大容量数组,占用内存空间,不适合超大范围素数筛选;
-
仍存在少量重复标记(相较于线性筛),极致性能场景可使用欧拉线性筛优化。
七、拓展修改方式
-
修改筛选范围 :直接修改主函数中
int n=100;的数值,即可筛选任意范围内的素数(不超过 MAXN 最大值); -
扩大筛选上限 :修改宏定义
MAXN的数值,可支持更大范围筛选; -
统计素数个数:可新增计数器,遍历过程中统计范围内素数总数量。
八、总结
埃氏筛法是C语言算法入门的核心知识点,也是笔试、刷题的高频考点。相比于暴力判断,该算法通过空间换时间的思路,大幅提升了素数筛选效率。本文代码可直接复制编译运行,格式规范、注释详细,适合新手学习和项目直接使用。