算法是一系列解决问题的明确指令,也就是说,对于符合一定规范的输入,能够在有限时间内获得要求的输出。
定义中使用了“指令”这个词,这意味着有人或物能够理解和执行所给的命令。我们将这种人或物称为computer。
算法靠计算机实现,但算法概念本身并不依赖于这样的假设。
为了阐明算法的概念,本节将以三种方法为例解决同一个问题,即计算两个整数的最大公约数。
算法的特点:
在《几何原本》中有一个算法,用现代数学的术语来表述,欧几里得算法采用的方法就是重复应用下列等式,直到m mod n等于0.
gcd(m,n)=gcd(n,m mod n)(mod表示取余数)
因为gcd(m,0)=m,m最后的取值也就是m和n的初值的最大公约数。
下面是该算法的一个更加结构化的描述:
用于计算gcd(m,n)的欧几里得算法
第一步:如果n=0,返回m的值作为结果,同时过程结束;否则,进入第二步;
第二步:m除以n,将余数赋给r。
第三步:将n的值赋给m,将r的值赋给n,返回第一步。
用伪代码来描述:
算法
Euclid(m,n)
//使用欧几里得算法计算gcd(m,n)
//输入:两个不全为0的非负整数m,n
//输出:m,n的最大公约数
while n≠0 do
r<-m mod n
m<-n
n<-r
return m
每次经过一次循环,参加运算的两个算子中后一个都会变得更小,而绝对不会变成负数。确实,下一次循环时,n的新值是m mod n,这个值总是比n小。所以,第二个算子的值最终会变成0,此时算法也就结束了。
就像其他许多问题一样,最大公约数也有很多种算法。还有两种方法。第一种方法只基于最大公约数的定义:m和n的最大公约数就是能够同时整除它们的最大正胜数。显然,这样一个公约数不会大于两个数中的较小值,因此,我们先有:t=min{m,n}。我们现在可以开始检查t是否能够整除m和n:如果能,t就是最大公约数;如果不能,我们将t-1,然后继续尝试。
用于计算gcd(m,n)的连续整数检查算法
第一步:将min{m,n}的值赋给t。
第二步:m除以t。如果余数为0,进入第三步;否则进入第四步
第三步:n除以t。如果余数为0,返回t的值作为结果;否则进入第四步。
第四步:把t的值减1.返回第二步。
注意,和欧几里得算法不同,按照这个算法的当前形式,当它的一个输入为0,计算出来的结果是错误的。
中学时计算gcd(m,n)的过程
第一步:找到m的所有质因数。
第二步:找到n的所有质因数。
第三步:从第一步和第二步求得的质因数分解式中找出所有的公因数(如果p是一个公因数,而且在m和n的质因数分解式分别找出出现果pm和pn次,那么应该将p重复min{pm,pn}次)。
第四步:将第三步中找到的质因数相乘,其结果作为给定数字的最大公约数。
有一个更加简单的算法,用来产生一个不大于给定整数n的连续质数序列。称为“埃拉托色尼筛选法”。该算法一开始初始化一个2~n的连续整数序列,作为候选质数。然后,在算法的第一个循环中,他将类似4和6这样的2的倍数从序列中消去。然后它指向列表中的下一个数字3,又将其倍数消去(我们这里的做法过于直接,增加了不必要的开销。因为有些数字被消了不止一次),不必处理数字4,因为4本身和它的倍数都是2的倍数,它们已经在前面的步骤中被消去了。第三步处理序列中剩余的下一个元素5.该算法以这种方法不断做下去,直至序列中已经没有可消去的元素为止。序列中剩下的整数就是我们要求得质数。
对于这个例子来说,更多步骤已经是多余了。因为它们只会消去在算法的前面循环中已经消去的数字。序列剩下的数字就是小于等于25的连续质数。
其倍数仍未消去的最大数p应该满足什么条件。注意:如果在当前步骤中,我们正在消去p的倍数,那么第一个指的考虑的倍数就是p×p,因为其他更小的倍数2p,…,(p-1)p已经在先前的步骤中从序列里消去了。显然p×p不会大于n,p也不会大于(n)1/2向下取整的值(记作⌊(n)1/2⌋,称为向下取整函数)
算法:Sieven(n)
//实现“埃拉托色尼筛选法”
//输入:一个正整数n>1