算法初体验之欧几里得算法

通过本文希望能给程序设计的初学者一些启发。

本文重点讲述欧几里得算法,引出算法的三大前提,大概阐明算法的一些特点。

欧几里得算法(或辗转相除法)用于计算两个正整数的最大公约数,基本算法如下:

E:设两个正整数m,n,且已知m>n

E1:令r=m%n('%'代表取余)

E2:若r=0(即n整除m),结束运算,n即为结果

E3:否则令m=n,n=r,并返回步骤E1

欧几里得算法运用了这样一个等价式(设gcd(m,n)代表m和n的最大公约数,mod()代表取余运算或模运算)gcd(m,n)=gcd(n,mod(m,n))。也就是m,n的最大公约数等于他们相除余数(r)和n的最大公约数。

下面来证明一下这个等式:

1.因为任意两个正整数都有最大公因数,设为d

2.将m,n分别用最大公因数d来表示为m=k1d,n=k2d(k1,k2是两个常数)

3.设k3=m/n('/'代表相除取整),有r=m-k3n,将m,n代换得r=k1d-k3k2d,所以r=(k1-k3k2)d

由此可得r是最大公因数d的倍数,得证gcd(m,n)=gcd(n,mod(m,n)),所以以此类推,可以将m,n中较大的数用较小的余数r替换,实现了降维,所以有了E3中的步骤,而欧几里得算法的优点就在于此。

相比之下利用穷举法来计算最大公约数,其比较次数与计算量都大出很多。

C语言实现欧几里得算法代码如下:

//功能:计算两个正整数的最大公约数
//参数:m,n
//返回:m,n的最大公约数,类型为int整形
#include
#include


int gcd(int m,int n)
{
    int t,r;
    if (m    {
        t=m;
        m=n;
        n=t;
    }
    while((m%n)!=0)//辗转相除
    {
        r=m%n;
        m=n;
        n=r;
    }
    return n;
}
int main()//主函数调用函数gcd()
{
    int m,n;
    scanf("%d%d",&m,&n);
    printf("%d",gcd(m,n));
    return 0;

}

采用穷举实现最大公约数的算法的C语言实现如下:

//功能:计算两个正整数的最大公约数
//参数:m,n
//返回:m,n的最大公约数,类型为int整形
#include
#include


int gcd(int m,int n)
{
    int i=n;
    for (i=n;i>1;i--)//逐个递减计算,递减计算不需要将全部数进行计算,当计算停止时就是最大值,若递增计算需要全部计算
    {
        if (m%i==0&&n%i==0)
        {
            break;
        }
    }
    return i;
}
int main()//主函数调用函数gcd()
{
    int m,n;
    scanf("%d%d",&m,&n);
    printf("%d",gcd(m,n));
    return 0;

}

欧几里得算法是学习计算机最初接触到的最基础的几个算法之一,对初学者而言算法被看做是解决一类事件的通用方法,只要是满足事件(或者叫做满足这种关系)的参数按照算法步骤就能得到准确结果。其实这样理解可以说大体意思没有问题,但是缺少细节约束。

算法有三大约束条件:

一:有穷性     二:确切性     三:可行性

①有穷性

计算机顾名思义是用于计算的,如果无法计算出最终结果那就没有意义。当一个程序的步骤有无穷多,我们无法得到一个结果,这对于我们使用计算机的人来说就没有意义,例如下列代码:

for (i=0; ;i++)
{
    

}

上面代码可以得到一个无穷大的数,显而易见这是没有意义的。这样的代码段称为死循环,算法设计中一定避免死循环。我们回看欧几里得算法,他的有穷性是肯定的,因为任意两个正整数一定有公因数。

②确切性

这一部分初学者掌握的相对较好,在最初的程序设计中进行练习的大部分是数学问题,数学问题本身就是逻辑严密,确切性很好的问题。在日常生活中有些事情有着和算法一样的明确的步骤,但是会有一些表示程度的词汇(倒一些水,走得慢一点),一些,一点,这样的表示程度的词语使得最终的结果不会是唯一的,而算法中唯一的输入必然对应唯一的输出。算法步骤一定是逻辑严密,没有歧义的准确表达。这和计算机语言使用符号化的表示方式是一个道理。

欧几里得算法中,三个步骤是确切的,准确的表述

③可行性

计算机世界给我们带来的一直是快节奏,计算机的优点就是计算快速,所以我们也希望我们的算法步骤能在较快时间内运行结束。一个算法有穷,但是计算时间过长也是不被允许的。如果一个算法需要计算十年或者更长,那我们利用计算机的意义何在。


一个优秀的算法,不单是能够计算,能得到结果,他的运行效率也是相当重要的。

你可能感兴趣的:(算法初体验之欧几里得算法)