前言
This Series aritcles are all based on the book 《經典算法大全》; 對於該書的所有案例進行一個探究和拓展,並且用python和C++進行實現; 目的是熟悉常用算法過程中的技巧和邏輯拓展。
提出問題
15.Algorithm Gossip: 篩選求質數(Eratosthenes )
說明
除了自身之外,無法被其它整數整除的數稱之爲質數.
篩選原理
逐步選出小質數對應的集合元素, 直到篩選質數到 sqrt(N)。
分析和解釋
計算素數的一個方法是埃氏篩法,它的算法理解起來非常簡單:
首先,列出從2開始的所有自然數,構造一個序列:
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …
取序列的第一個數2,它一定是素數,然後用2把序列的2的倍數篩掉:
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …
取新序列的第一個數3,它一定是素數,然後用3把序列的3的倍數篩掉:
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …
取新序列的第一個數5,然後用5把序列的5的倍數篩掉:
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …
不斷篩下去,就可以得到所有的素數。
用Python來實現這個算法,可以先構造一個從3開始的奇數序列:
代碼
C語言有待改進的示例
#include <stdio.h>
#include <stdlib.h>
#define N 1000
int main(void) {
int i, j;
int prime[N+1];
for(i = 2; i <= N;i++)
prime[i] = 1;
for(i = 2; i*i <= N;i++) {
if(prime[i] == 1) {
for(j = 2*i; j <= N;j++) {
if(j % i == 0)
prime[j] = 0;
}
}
}
for(i = 2; i < N;i++) {
if(prime[i] == 1) {
printf("%4d ", i);
if(i % 16 == 0)
printf("\n");
}
}
printf("\n");
return 0;
}
python 的 fitter 實現
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
# 篩選函數
def _not_divisible(n):
return lambda x: x % n > 0
#生成器, 不斷返回素數
def primes():
yield 2
it = _odd_iter() # 初始序列
while True:
n = next(it) # 返回序列的第一個數
yield n
it = filter(_not_divisible(n), it) # 構造新序列
##主函數
for n in primes():
if n < 1000:
print(n)
else:
break
PS, 對 fitter , yied 不熟悉的可以百度瞭解下生成器和迭代器。
yied 主要用於不斷生成目標返回到元組的一種append方式 -> 生成器, fitter 爲刪選機制。
拓展和關聯
後記
參考書籍
- 《經典算法大全》
- 維基百科