最大公约数四大算法---不同数据规模算法平均运行时间

最大公约数之“四大天王”算法
1.辗转相除法

2.穷举法

3.更相减损法

4.Stein算法

算法一 辗转相除法
算法过程:前提:设两数为a,b设其中a 做被除数,b做除数,temp为余数
(1)大数放a中、小数放b中;
(2)求a/b的余数;
(3)若temp=0则b为最大公约数;
(4)如果temp!=0则把b的值给a、temp的值给a;
(5)返回第二步;

        //辗转相除法
        public int divisor1(int a,int b){
            int temp;
            if(a < b){
                temp = a;
                a = b;
                b = temp;
            }
            while(b != 0){
                temp = a%b;
                a = b;
                b = temp;
            }
            return a;

        }

流程图在下吧,受我一拜
在这里插入图片描述
算法二 穷举法
算法过程:前提:设两数为a,b。其中,a为较大值,b为较小值
(1)两个数中较小数开始由大到小列举;
(2)直到找到公约数立即中断列举;
(3)即得到的公约数便是最大公约数;

//穷举法
public int divisor2(int a,int b){
            int temp = a<b?a:b;
            while(temp > 0){
                if(a%temp==0 && b%temp==0){
                    break;
                }
                temp--;
            }
            return temp;
        }

流程图在下吧,受我一拜
在这里插入图片描述
算法三 更相减损法
算法过程:
(1)任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步;
(2)以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
(3)则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。

//更相减损法
public int divisor3(int a,int b){
            int temp;
            int count = 0;
            while(a%2==0 && b%2==0){
                a /= 2;
                b /= 2;
                count++;
            }
            //保证a大于b
            if(a < b){
                temp = a;
                a = b;
                b = temp;
            }
            while((a-b) != 0){
                temp = a - b;
                a = temp>b?temp:b;//a保存较大值
                b = temp<b?temp:b;//b保存较小值
                if(temp == (a - b)){
                    break;
                }
            }
            if(count == 0){
                return b;
            }else{
                return (int)Math.pow(2,count)*b;
            }
        }

流程图在下吧,受我一拜
在这里插入图片描述
算法四 Stein算法
算法过程:对两个正整数 x>y :
(1)均为偶数 divisor4( x,y ) =2*divisor( x/2,y/2 );
(2)均为奇数 divisor4( x,y ) = divisor4( (x+y)/2,(x-y)/2 );
(3)x奇y偶 divisor4( x,y ) = divisor4( x,y/2 );
(4)x偶y奇 divisor4(x,y) = divisor4(x/2,y) 或 divisor4(x,y) = divisor4(x,y/2);

//Stein算法
public int divisor4(int a,int b) {
            int m, n;
            m = a >= b ? a : b;   //m保存a、b中的较大者
            n = a < b ? a : b;    //n保存a、b中的较小者
            if (0 == n)
                return m;
            if(m%2 == 0&&n%2 == 0)//m偶数n偶数
                return 2 * divisor4(m / 2, n / 2);
            if (m % 2 == 0)//m偶数n奇数
                return divisor4(m / 2, n);
            if (n % 2 == 0)//m奇数n偶数
                return divisor4(m, n / 2);
            return divisor4((m + n) / 2, (m - n) / 2);//m奇数n奇数
        }

流程图在下吧,受我一拜
在这里插入图片描述
关键算法已就绪;
关键问题1:数据的产生
利用Random产生随机数,组成一个二维数组,每一组数据即为二维数组的一个元素。
核心算法如下:

Random random=new Random();
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入测试数据规模:");
        int num = sc.nextInt();
        int[][] array=new int[num][2];//声明二维数组
        //给数组赋值
        for(int i=0;i<num;i++){
            for(int j=0;j<2;j++){
               //在0-100内随机生成一个正整数
                array[i][j]= random.nextInt(100);
            }
        }

关键问题2:平均运行时间的计算
java中有特定的求运行时间的代码程序
time = (结束时间 - 开始时间)/算法执行次数,单位:ns(纳秒)
核心算法如下:

long start1=System.nanoTime();   //获取开始时间
        for(int i=0;i<array.length;i++){
            new MaxDivisor().divisor1(array[i][0],array[i][1]);
        }
        long end1=System.nanoTime(); //获取结束时间
        System.out.println("程序运行时间: "+(end1-start1)/array.length+"ns");

哈哈哈,主要组成部分一一列举了,接下来,双手奉上“四大天王”源程序代码,程序好像啰里啰唆的,要是看源程序代码get不到重点的话,可以看上面列举的代码块哦

import java.util.Random;
import java.util.Scanner;

/**
 * @Author:Star
 * @Date:Created in 1:06 2019/3/9
 * @Description:测试不同算法在不同数据规模下的平均运行时间
 */
public class Test1 {
    public static void main(String[] args) {
        Random random=new Random();
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入测试数据规模:");
        int num = sc.nextInt();
        int[][] array=new int[num][2];//声明二维数组
        //给数组赋值
        for(int i=0;i<num;i++){
            for(int j=0;j<2;j++){
               //在0-100内随机生成一个正整数
                array[i][j]= random.nextInt(100);
            }
        }
        //计算不同算法在相同数据规模下的平均运行时间
        new TextTime().time(array);
    }
}

    class MaxDivisor{
        //辗转相除法
        public int divisor1(int a,int b){
            int temp;
            if(a < b){
                temp = a;
                a = b;
                b = temp;
            }
            while(b != 0){
                temp = a%b;
                a = b;
                b = temp;
            }
            return a;

        }
        //穷举法
        public int divisor2(int a,int b){
            int temp = a<b?a:b;
            while(temp > 0){
                if(a%temp==0 && b%temp==0){
                    break;
                }
                temp--;
            }
            return temp;
        }
        //更相减损法
        public int divisor3(int a,int b){
            int temp;
            int count = 0;
            while(a%2==0 && b%2==0){
                a /= 2;
                b /= 2;
                count++;
            }
            //保证a大于b
            if(a < b){
                temp = a;
                a = b;
                b = temp;
            }
            while((a-b) != 0){
                temp = a - b;
                a = temp>b?temp:b;//a保存较大值
                b = temp<b?temp:b;//b保存较小值
                if(temp == (a - b)){
                    break;
                }
            }
            if(count == 0){
                return b;
            }else{
                return (int)Math.pow(2,count)*b;
            }
        }
        //Stein算法
        public int divisor4(int a,int b) {
            int m, n;
            m = a >= b ? a : b;   //m保存a、b中的较大者
            n = a < b ? a : b;    //n保存a、b中的较小者
            if (0 == n)
                return m;
            if(m%2 == 0&&n%2 == 0)//m偶数n偶数
                return 2 * divisor4(m / 2, n / 2);
            if (m % 2 == 0)//m偶数n奇数
                return divisor4(m / 2, n);
            if (n % 2 == 0)//m奇数n偶数
                return divisor4(m, n / 2);
            return divisor4((m + n) / 2, (m - n) / 2);//m奇数n奇数
        }
    }

    class TextTime{
    public void time(int[][] array){
        long start1=System.nanoTime();   //获取开始时间
        for(int i=0;i<array.length;i++){
            new MaxDivisor().divisor1(array[i][0],array[i][1]);
        }
        long end1=System.nanoTime(); //获取结束时间
        System.out.println("程序运行时间: "+(end1-start1)/array.length+"ns");

        long start2=System.nanoTime();   //获取开始时间
        for(int i=0;i<array.length;i++){
            new MaxDivisor().divisor2(array[i][0],array[i][1]);
        }
        long end2=System.nanoTime(); //获取结束时间
        System.out.println("程序运行时间: "+(end2-start2)/array.length+"ns");

        long start3=System.nanoTime();   //获取开始时间
        for(int i=0;i<array.length;i++){
            new MaxDivisor().divisor1(array[i][0],array[i][1]);
        }
        long end3=System.nanoTime(); //获取结束时间
        System.out.println("程序运行时间: "+(end3-start3)/array.length+"ns");

        long start4=System.nanoTime();   //获取开始时间
        for(int i=0;i<array.length;i++){
            new MaxDivisor().divisor1(array[i][0],array[i][1]);
        }
        long end4=System.nanoTime(); //获取结束时间
        System.out.println("程序运行时间: "+(end4-start4)/array.length+"ns");
    }
    }

程序结束
接下来给大家分享一下我的测试结果
1.数据规模----10组数据
在这里插入图片描述
2.数据规模----20组数据
在这里插入图片描述
3.数据规模----40组数据
在这里插入图片描述
4.数据规模----100组数据
在这里插入图片描述
想要看更大数据规模,可以自己去练习哦

最最重要的部分来了-------今日份的自我检讨
1.突然发现原来最大公约数求解的算法这么多,唉,好想静静;
2.面对大规模数据,还是要选平均运行时间优胜的算法来实现,学到了学到了学到了;
3.程序中,我在比较不同算法在相同数据及数据规模的前提下,写了很多重复的代码,代码缺乏了相对间接性,比较四个算法,我写了四遍,但是,我一直在想,要是有100个算法,我是不是要写100遍,啊啊啊啊,苦思冥想半天,还是硬着头发不好意思的复制粘贴修改了三遍。

最后,想说一个大事:
如果有哪位实在看不下去我写的代码(包括我的丑流程图),可以留言给我,帮帮我这傻孩子。希望大佬们不吝赐教。(手动鞠躬)

猜你喜欢

转载自blog.csdn.net/weixin_44369212/article/details/88370069