您的位置:首页 > 其它

多个数的最大公约数

2015-11-24 23:25 197 查看

http://www.cnblogs.com/qingergege/p/4992990.html

---恢复内容开始---

最近在看一本算法的书。讲的都是一些基本的问题,并没有涉及很复杂的算法,或者说这本书更看重技巧。

其中开篇就讲了最大公约数的算法,觉得有可取之处,和大家分享一下。

提到最大公约数我们最先想到的一定是辗转相除法。

没错,永远不要蔑视我们的祖先,他们的智慧是无穷的。(扯远了,嘿嘿)

我们都在用辗转相除法来求最大公约数,却很少去想为什么辗转相除法就能求最大公约数呢?或者说怎么证明算法的正确性呢(至少我之前完全没有想过)。

这里我们感性的认识一下辗转相除法(不是很严格地证明一下)。

假设两个数a,b且a>b。 设a除以b商k,余数为r,那么会有a=k*b+r,那么b和r的最大公约数,就是a和b的最大公约数。所以问题就转换求成除数和余数的最大公约数,依次递归,递归的出口就是一个已知的条件:如果a能够被b整除,那么b就是a和b的最大公约数,所以辗转相除法递归代码如下:

int GCD1(int num1,int num2)

{

  if(num1%num2==0)

  {

  return num2;

   }

  else

  {

  int next1=num2;

   int next2=num1%num2;

  return GCD1(next1,next2);

   }

}

还有一种我们耳熟能详的求最大公约数的算法就是更相减损术,他的基本思想就是:两个数a,b且a>b,那么令c=a-b,然后把 b和c看成新的a和b,递归下去,递归出口就是一个已知的条件:如果a=b,那么a和b的最大公约数就是a或b。其实更相减损术和辗转相除法是一个东东,更相减损术就是让辗转相除法中的商(k)恒为1,所以大多数情况下,辗转相除法的效率要比更相减损术的效率高。给出更相减损术的代码:

int GCD2(int num1,int num2)

{

  if(num1==num2)

  {

     return num2;

  }

  else

  {

    int next1= (num1>num2)? (num1-num2):(num2-num1);

    int next2= (num1>num2)?num2:num1;

    if(next1>next2)

    {

    return GCD2(next1,next2);

    }

    else

    {

      return GCD2(next2,next1);

    }

  }

}

好了,步入这次的正题:多个数求最大公约数(实际上就是辗转相除法的扩展)给出算法:

设一组数a1,a2,a3,a4,a5..

(1)对这一组数进行排序(从大到小)

(2)对每两个相邻的两个数进行如下操作:

    设相邻的两个数为A和B(A在前,因为已经排序,所以A>B),如果A=n*B(n为整数),也就是A能够被B整除,那么就令A=B;如果A不能被B整除则令A=A%B。

(3)重复(1)、(2)知道数组中每个数都相等,则最大公约数就为这个数。

给出完整程序:

#include<iostream>

using namespace std;

void Sort(int* num,int n);

int GCD3(const int* num,int n);

int main()

{

  int num[4]={756,504,630,2226};

  int result=GCD3(num,4);

  cout<<"数组:";

  for(int i=0;i<4;i++)

  {

    cout<<num[i]<<" ";

  }

  cout<<"的最大公约数为:"<<result<<endl;

  return 0;

}

int GCD3(const int* num,int n)

{

  int *temp=new int
;

  for(int i=0;i<n;i++)

  {

    temp[i]=num[i];

  }

  do

  {

    if(temp[0]==temp[n-1])

    {

      break;

    }

    else

    {

      Sort(temp,n);//排序

      for(int i=0;i<n-1;i++)

      {

        if(temp[i]%temp[i+1]==0)

        {

           temp[i]=temp[i+1];

        }

        else

        {

          temp[i]=temp[i]%temp[i+1];

        }

      }

    }

  }while(temp[0]!=temp[n-1]);

  return temp[0];

}

//排序

void Sort(int* num,int n)

{

  //冒泡排序法

  for(int i=0;i<n-1;i++)

  {

    for(int j=i;j<n-1;j++)

    {

      if(num[i]<num[j+1])

      {

        int temp=num[i];

        num[i]=num[j+1];

        num[j+1]=temp;

      }

    }

   }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: