C语言埃氏筛法(素数筛选)

一、算法简介

埃拉托斯特尼筛法(埃氏筛) 是最经典、最高效的素数筛选算法之一,专门用于快速筛选出 2~n 范围内的所有素数。相比于普通暴力枚举判断素数的方法,埃氏筛通过倍数标记法剔除合数,极大降低了时间复杂度。

普通素数判断时间复杂度:O(n\\sqrt{n})

埃氏筛算法时间复杂度:O(n\\log\\log n)

该算法核心思想:素数的所有倍数一定是合数,只需遍历每个素数,将其所有倍数标记为合数,最终未被标记的数即为素数。

二、算法核心原理

  1. 数组初始化:定义布尔数组,默认将所有数字标记为素数;

  2. 特殊值剔除:0 和 1 不属于素数,手动标记为非素数;

  3. 遍历筛选:从 2 开始遍历,若当前数是素数,则将其所有平方及以上的倍数标记为合数(优化点:从 i\*i 开始遍历,避免重复筛选);

  4. 结果输出:遍历数组,所有标记为 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. 筛法核心函数

  1. 数组初始化:将 0~n 所有数值默认标记为素数;

  2. 特殊处理:0、1 不是素数,强制标记为 false;

  3. 外层循环:只遍历到 \\sqrt{n},减少循环次数(合数一定存在小于自身的因数);

  4. 内层循环:对每个素数 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 起始优化,规避了重复筛选问题。

❌ 缺点

  • 需要开辟大容量数组,占用内存空间,不适合超大范围素数筛选;

  • 仍存在少量重复标记(相较于线性筛),极致性能场景可使用欧拉线性筛优化。

七、拓展修改方式

  1. 修改筛选范围 :直接修改主函数中 int n=100; 的数值,即可筛选任意范围内的素数(不超过 MAXN 最大值);

  2. 扩大筛选上限 :修改宏定义 MAXN 的数值,可支持更大范围筛选;

  3. 统计素数个数:可新增计数器,遍历过程中统计范围内素数总数量。

八、总结

埃氏筛法是C语言算法入门的核心知识点,也是笔试、刷题的高频考点。相比于暴力判断,该算法通过空间换时间的思路,大幅提升了素数筛选效率。本文代码可直接复制编译运行,格式规范、注释详细,适合新手学习和项目直接使用。

相关推荐
Omics Pro2 小时前
Cell封面|衰老生物学开源AI工具包
数据库·人工智能·算法·机器学习·自然语言处理
释厄6234 小时前
多黑洞具现论·物理/生物/金融三域显化·虚拟宇宙黑洞·奇点=0 圆圈
开发语言·数据结构·人工智能·程序人生·安全威胁分析
UIU1145 小时前
递归算法与汉诺塔
c++·学习·算法·c#·递归
用户9799848071810 小时前
200 行代码写一个能跑的 AI Agent:不依赖任何框架,只靠 tool-calling 原理
算法
threerocks10 小时前
【Muse实战】X 流量作战室搭建保姆级教程 - 拥有你自己的运营团队
算法
GreenTea10 小时前
深度拆解 ScienceBuddy:如何用“双层递归自进化”构建高可靠科研 Agent Harness
前端·后端·算法
花椒技术10 小时前
2.46 秒生成 5 秒视频:拆解 H3 Max 的模型、推理栈与硬件协同
算法·音视频开发·视频编码
vivo互联网技术10 小时前
ART:妆容迁移框架,重新定义高保真妆容迁移 | ECCV 2026
人工智能·算法·图像识别
用户04414409244910 小时前
卫星信号模拟器里的四个坐标转换公式
算法