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

相关推荐
Zwawa6 分钟前
让电机走到指定位置:编码器位置环 PID
c语言·单片机·嵌入式
倚楼听风语9 分钟前
Kotlin 协程与 suspend 原理详解
java·算法·kotlin
程序员清风11 分钟前
双指针与滑动窗口:高效处理连续区间
开发语言·算法
代钦塔拉16 分钟前
【C++/Qt 进阶】设计模式系列(2):工厂模式——从游戏角色到披萨店
c++·算法·设计模式
思茂信息21 分钟前
电磁仿真学涉及哪些算法?
人工智能·算法·数学建模·matlab·emc·电磁仿真·仿真辐射
糖果豆豆43 分钟前
让 AI 自查三遍,它只会把错的说得更像对的——检查的人和被检查的,是同一个
算法·架构
fensnote1 小时前
西门子 S7 PLC 内部寄存器读写 Demo(C 语言)
c语言·开发语言
总裁余(余登武)2 小时前
K-means算法改进(Python版)
python·算法·kmeans
灯澜忆梦2 小时前
【面向对象编程c++】| 指针与自定义数据类型
开发语言·c++·算法
xxwl5853 小时前
区域赛算法模版第八章---贪心(Greedy)
c++·笔记·学习·算法