首页 » 算法技术手册 » 算法技术手册全文在线阅读

《算法技术手册》讨论5b:性能不明显的计算

关灯直达底部

在很多情况下,通过算法的描述(如加法和乘法)就已经足够分辨一个算法是线性的还是二次方的。例如二次方的主要特征,是嵌入的循环结构。但是,有一些算法不能够使用如此直接的分析。让我们来看看例2-5的GCD算法,这个算法是由欧几里德设计,用来计算两个整数的最大公约数。

例2-5:欧几里德GCD算法

这个算法不断地比较a和b,然后用大数减去小数直到得到0为止。这个实现的辅助函数(isZero、assign、compareTo和subtract)没有在这里给出,不过能够在代码库中找到。

这个算法计算出了两个数的最大公约数,但是对于给定输入的规模,要经过多少次迭代,这个答案并不明显。在每一次循环之后,a或者b都不会为负,所以我们能够保证这个算法会结束,但是一些GCD的计算可能会需要比较长的时间,例如,这个算法计算gcd(1000,1)会执行999步!现在这个算法的性能对于输入数据比乘法和加法算法要敏感得多,对于相同规模的输入来说,gcd算法的时间是随着输入数据的变化而变化的。gcd算法在计算(10n-1,1)的最大公约数时性能最差,它需要处理10n-1次循环!我们已经知道加法和减法在数据规模为n时时间复杂度为O(n),gcd总共需要n*(10n-1)次操作。把这个等式转换到二进制上来,我们得到n*(23.3219*n)-n,这个等式是指数级的,所以我们认为这个算法是O(n*2n)。

例2-6中MODGCD算法的性能要比例2-5的gcd实现好得多,这个算法使用取模计算一个数模b的余数。

例2-6:MODGCD算法计算最大公约数

MODGCD将能够更快地得到解,因为它不会不断地在while循环中从大数中减去小数。这个差异并不仅仅是实现细节的差异,它告诉我们,在解决问题时,要融会贯通。

图2-7(也在表2-5中进行了枚举)描绘了对10 011对随机产生的142位数求最大公约数的计算结果。

图 2-7 比较gcd和MODGCD算法

即使MODGCD实现比其他的gcd实现快60%,MODGCD的性能仍然是二次方,也就是O(n2),但是gcd算法却是指数级的。也就是说,gcd的最坏性能(不会在小数据集下展现)会比MODGCD的最坏性能要慢几个数量级。

更好的计算最大公约数的算法已经设计出来了,但是除非是特别大的整数,很多都由于实现复杂度太高而不可能投入使用。通过分析这个问题,也表明需要更加高效的算法。