今天写一下最大公约数算法,英文简称为Gcd算法。
/*书上并没有给出递归的解法,可能是觉得这个解法不是很完美,但是给出来就当学习下递归。*/
int Gcd(unsigned num1, unsigned num2){
if (num1 == 0 || num2 == 0)//算法基于欧几里德的算法。
return (num1 > num2) ? num1 : num2;
return Gcd(num2, num1%num2);
}
//代码写的很短小,但是效率可能不是很高
//欧几里德算法有一个结论,两个整数A,B.如果A,B有一个为0,那么另一个就是最大公约数。其余的内容可以谷歌。
//这个地方装逼使用了C++11的特性,但可能用的不是很好。
//回去翻翻书争取用C++11特性重新优化下写法。
int&& Gcd(const unsigned &num1,const unsigned &num2){
if (num1 == 0 || num2 == 0)
return std::move((num1 > num2) ? num1 : num2);
int gcd = 0;
for (int i = 1; i < int(num1); ++i){
if ((num1%i == 0 )&& (num2%i == 0))
gcd = i;
else
continue;
}
return std::move(gcd);
}
//这个地方想法也很巧妙,属于正常的想法。既然我们求的是最大公约数,那么我们可以从1开始尝试,最大公约数肯定小于等于任意给定的两个整数,我们只需要用循环从1开始尝试,保存满足(num1%i == 0 )&& (num2%i == 0)条件的最大i 即可。
int Gcd(unsigned num1, unsigned num2){
if (num1 == 0 || num2 == 0)
return (num1 > num2) ? num1 : num2; //上面一行和本行不是必须的。
while (num2 > 0){
int rem = num1%num2;
num1 = num2;
num2 = rem;
}
return num1;
//原理和上面类似,递归可以和循环互改。
这个地方的优化估计主要是对参数的优化了,对算法本身我并没有更好的解法。
int Gcd(const unsigned& num1, const unsigned& num2){
if (num1 == 0 || num2 == 0)
return (num1 > num2) ? num1 : num2;
return Gcd(num2, num1%num2);
}
//上面针对函数的传入参数进行了优化。有传值调用改为了const 引用。避免了参数的拷贝,但是这个算法并不是万能的,因为在循环的算法中我们是不允许修改const属性的值。所以我们使用右值引用写一下。
//下面代码中我修改了返回类型和传入的参数类型。改成了右值引用类型。
//所谓右值引用就是对右值的引用。我们以前学习的都是左值引用。
//左右值区分可以通过取址来判断。和右值相关出现了一个move语意,实现了资源的转移,而不是通过拷贝。
//看过一个形象的例子:个冰箱里放了一个大象,现在想把大象弄到另一个冰箱里。以前的做法是先复制一个大象,然后把复制的大象放到冰箱里,销毁最初的大象。但是有了右值引用之后,我们的做法是直接把第一个冰箱里的大象赶出来放到第二个冰箱里。至少少了一个复制和销毁的过程。至于详细就不谈了,毕竟写的重点是算法。
unsigned&& Gcd(unsigned &&num1, unsigned &&num2){
if (num1 == 0 || num2 == 0)
return std::move((num1 > num2) ? num1 : num2);
while (num2 > 0){
int rem = num1%num2;
num1 = num2;
num2 = rem;
}
std::cout << "Call the second function " << std::endl;
return std::move(num1);
}
//关于右值引用唠叨最后一句。只有当存在类型推断是才会存在通用引用类型(universial reference).
unsigned& Gcd(unsigned &&num1, unsigned &&num2,unsigned & value){
if (num1 == 0 || num2 == 0){
value = (num1 > num2) ? num1 : num2;
return value;
}
while (num2 > 0){
int rem = num1%num2;
num1 = num2;
num2 = rem;
}
value=num1;
return value;
}
//上面我传入了一个value参数,用于实现左值引用。
代码:
#include <iostream>
int Gcd(const unsigned& num1, const unsigned& num2){
if (num1 == 0 || num2 == 0)
return (num1 > num2) ? num1 : num2;
return Gcd(num2, num1%num2);
}
/*int Gcd(unsigned &num1, unsigned &num2){
if (num1 == 0 || num2 == 0)
return (num1 > num2) ? num1 : num2;
while (num2 > 0){
int rem = num1%num2;
num1 = num2;
num2 = rem;
}
std::cout << "Call the first function " << std::endl;
return num1;
}*/
unsigned& Gcd(unsigned &&num1, unsigned &&num2,unsigned & value){
if (num1 == 0 || num2 == 0){
value = (num1 > num2) ? num1 : num2;
return value;
}
while (num2 > 0){
int rem = num1%num2;
num1 = num2;
num2 = rem;
}
value=num1;
return value;
}
/*
int&& Gcd(const unsigned &num1,const unsigned &num2){
if (num1 == 0 || num2 == 0)
return std::move((num1 > num2) ? num1 : num2);
int gcd = 0;
for (int i = 1; i < int(num1); ++i){
if ((num1%i == 0 )&& (num2%i == 0))
gcd = i;
else
continue;
}
return std::move(gcd);
}*/
int main(){
//std::cout << Test_func(50, 20);
// std::cout << Gcd(40, 20);
int num1 = 40, num2 = 20;
unsigned gcd = 0;
Gcd(40,12,gcd)=5;
//std::cout << Gcd(40, 12, gcd);
system("pause");
return 0;
}
原文地址:http://blog.csdn.net/u014343243/article/details/44982791