码迷,mamicode.com
首页 > 编程语言 > 详细

算法交作业之最大公约数

时间:2015-04-10 22:33:05      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:递归   算法   

今天写一下最大公约数算法,英文简称为Gcd算法。

1.递归解法:

/*书上并没有给出递归的解法,可能是觉得这个解法不是很完美,但是给出来就当学习下递归。*/
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,那么另一个就是最大公约数。其余的内容可以谷歌。

2.for循环解法:

//这个地方装逼使用了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 即可。

3.while 循环解法:

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;
//原理和上面类似,递归可以和循环互改。

优化方案:

这个地方的优化估计主要是对参数的优化了,对算法本身我并没有更好的解法。

1.0

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属性的值。所以我们使用右值引用写一下。

2.0

//下面代码中我修改了返回类型和传入的参数类型。改成了右值引用类型。
//所谓右值引用就是对右值的引用。我们以前学习的都是左值引用。
//左右值区分可以通过取址来判断。和右值相关出现了一个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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!