筛法(Sieve Method)简介
文章目录
- 筛法(Sieve Method)简介
- 埃氏筛法(Sieve of Eratosthenes)
- 算法步骤
- C++代码实现
- 代码解析
- 运行示例
- 时间复杂度
- 空间复杂度
- 优化:空间复杂度优化
- 结论
筛法(Sieve Method)简介
筛法是一种用于解决素数问题的高效算法,特别适用于找出一定范围内的所有素数。筛法的基本思想是,通过逐步标记非素数,从而筛选出素数。最常见的筛法是 埃氏筛法(Sieve of Eratosthenes),用于找出从1到n的所有素数。其时间复杂度较低,适用于大范围素数的查找。
在这篇文章中,我们将详细介绍埃氏筛法的实现原理,并给出 C++ 代码实现。
埃氏筛法(Sieve of Eratosthenes)
埃氏筛法的核心思想是:
- 从2开始,将所有倍数标记为非素数(即合数)。
- 对每个尚未被标记为合数的数,标记其倍数为合数,直到当前数的平方大于n为止。
- 剩下的未被标记的数即为素数。
算法步骤
- 初始化一个布尔数组
is_prime
,假设所有数都为素数(值为true
)。 - 从2开始,对于每一个数
p
,如果它是素数,则标记p
的所有倍数为合数(false
)。 - 重复上述过程直到
p * p > n
。 - 最终,所有
is_prime[i]
为true
的数i
就是素数。
C++代码实现
#include <iostream>
#include <vector>
using namespace std;class SieveOfEratosthenes {
public:// 构造函数,初始化筛法SieveOfEratosthenes(int n) : n(n) {is_prime.resize(n + 1, true); // 初始化所有数为素数is_prime[0] = is_prime[1] = false; // 0 和 1 不是素数}// 执行筛法,找出所有小于等于 n 的素数void sieve() {for (int p = 2; p * p <= n; p++) {if (is_prime[p]) { // 如果 p 是素数// 标记 p 的所有倍数为合数for (int i = p * p; i <= n; i += p) {is_prime[i] = false;}}}}// 输出所有素数void printPrimes() {for (int i = 2; i <= n; i++) {if (is_prime[i]) {cout << i << " ";}}cout << endl;}private:int n;vector<bool> is_prime;
};int main() {int n;cout << "Enter the upper limit (n): ";cin >> n;// 创建筛法对象SieveOfEratosthenes sieve(n);// 执行筛法sieve.sieve();// 输出结果cout << "Prime numbers up to " << n << " are: ";sieve.printPrimes();return 0;
}
代码解析
-
SieveOfEratosthenes 类:
- 构造函数接受一个整数
n
,表示我们要筛选的范围。 is_prime
是一个布尔类型的数组,is_prime[i]
为true
表示i
是素数,为false
表示i
不是素数。初始化时,我们假设所有数字都是素数。sieve()
方法执行埃氏筛法,从 2 开始标记所有倍数为合数。printPrimes()
方法用于输出所有的素数。
- 构造函数接受一个整数
-
main 函数:
- 用户输入上限
n
。 - 创建
SieveOfEratosthenes
类的实例,调用sieve()
方法筛选素数,最后通过printPrimes()
输出所有素数。
- 用户输入上限
运行示例
Enter the upper limit (n): 50
Prime numbers up to 50 are: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
时间复杂度
- 初始化数组
is_prime
的时间复杂度是 (O(n))。 - 外层循环从 2 到 ( \sqrt{n} ),因此最多执行 (O(\sqrt{n})) 次。
- 内层循环每次遍历
p
的倍数,总共执行 (O(n \log \log n)) 次。
因此,埃氏筛法的时间复杂度是 (O(n \log \log n)),这使得它在处理较大范围的素数时非常高效。
空间复杂度
- 我们使用一个大小为
n+1
的布尔数组is_prime
来存储每个数字是否是素数。因此,空间复杂度是 (O(n))。
优化:空间复杂度优化
我们还可以优化空间使用。例如,只存储小于 ( \sqrt{n} ) 的素数,并利用这些素数来筛选更大的数。这种优化被称为 线性筛法,可以进一步提高空间效率。
结论
埃氏筛法是一种非常高效的算法,能够快速找到一定范围内的所有素数。它的时间复杂度为 (O(n \log \log n)),适用于大规模素数查找问题。如果想要进一步优化,可以结合线性筛法进行空间优化。