算法学习 之 欧几里得算法和扩展欧几里得算法(一)

这是我算法学习标签下的第一篇随笔,首先我想声明,在看了很多博客后,我的想法就是,尽量不去盲目复制别人的东西,一个原因是盲目复制不一定能发现其文章中的错误,二是可以加深自己的理解程度,并且将博客写得通俗易懂,转载别人的东西一定要注明出处。还有我的一个习惯就是,把东西写短一点,所以有可能会将一个本来应在一篇文章的东西,写成好几节。


Euclidean Algorithm 又称辗转相除法,用途是求两个正整数a,b的最大公约数,gcd(a,b )表示a和b的最大公约数(gcd = greatest common divisor)。

 

内容:gcd(a,b)=gcd(b,a%b);

条件:a,b>0(当a%b=0时,使用该公式后就不能再使用)

 

关于最大公约数:前提是对于两个正整数而言,约数也必须是正整数。不会讨论 -4 8、4 0 等类似数的最大公约数,可以说是-4和8没有最大公约数,4和0也没有最大公约数。虽然对于次算法运行起来这两个是有结果的,-4和4。

 

证明:

将a表示为 a=kb+r,则 r=a%b , r=a-kb;

假设d为a,b的一个公约数,则a%d = 0 , b%d = 0  , 又r = a - kb,所以r % d = 0;

整理下:b % d = 0 , r % d = 0( (a % b) % d = 0 )

即 d也是b和a%b的公约数,所以a和b的最大公约数也是b和a%b的最大公约数。

 

递归形式代码:

#include<iostream>
using namespace std;

int gcd(int a,int b)
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}

int main()
{
    int a,b;
    cout<<"Please enter two integers:"<<endl;
    cin>>a>>b;
    cout<<a<<" and "<<b<<"'s gcd is:"<<endl;
    cout<<gcd(a,b)<<endl;
return 0;
}

 

非递归形式:

#include<iostream>
using namespace std;

int gcd(int a,int b)
{
    int temp;
    while(b!=0)
    {
        temp=b;
        b=a%b;
        a=temp;
    }
    return a;
}

int main()
{
    int a,b;
    cout<<"Please enter two integers:"<<endl;
    cin>>a>>b;
    cout<<a<<" and "<<b<<"'s gcd is:"<<endl;
    cout<<gcd(a,b)<<endl;
return 0;
}

 

运行截图:

 

有两点想说明的是:

1.出现类似gcd(4,0) 的含义并不是直接代表gcd(4,0)=4,因为4和0的公约数不存在。而是由前面的,得到了gcd(4,0),某个数mod 4 = 0,即有个数被4整除了,所以最大公约数是4。

 

2.网上有很多代码先判断了a与b的大小,a<b时候,要交换a与b的值。其实当a<b的时候,temp=b; b=a%b; a=temp;  就是一个swap的过程,所以交换位置是没有必要的。求gcd(4,8)=gcd(8,4)=...。

 

posted on 2015-05-14 09:59  _飛  阅读(554)  评论(0编辑  收藏  举报

导航