一、题目分析
欲运行四种求最大公约数的算法,并比较在不同测试数据规模下四种算法的平均运行时间
用文字描述步骤
- 输入测试数据的规模(数组大小);
- 调用random()函数,创建数组;
- 定义clock_t变量start,记录开始时刻;
- 调用求公约数函数,求出最大公约数;
- 定义clock_t变量stop,记录结束时刻;
- 输出运行时间;
二、算法流程图
三、源代码
/**
* 文件名:main.cpp
* 描述:完成求两个数的最大公约数问题,并输出“求公约数”的操作的运行时间
**/
#include"iostream"
#include<cstdlib>
#include<time.h>
#include"algorithm.h"
/*randomInt(a,b)规定生成的随机数在[a,b]范围内*/
#define randomInt(a,b) (rand()%(b-a+1)+a)
using namespace std;
int main()
{
char ch;
int n;
cout << "需要求多少组数据的最大公约数:";
cin >> n;
/*使用new动态分配存储空间,建立动态数组*/
int(*p)[2] = new int[n][2];
//生成随机数
srand((unsigned)time(NULL));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 2; j++)
{
//生成一个[1,1000]之间的随机数
p[i][j]=randomInt(1,1000);
}
}
cout << "可选择的求最大公约数的方法:" << endl;
cout << "1. 辗转相除法" << endl;
cout << "2. 穷举法" << endl;
cout << "3. 更相减损法" << endl;
cout << "4. Stein算法" << endl;
/*可重复选择*/
do{
cout << "输入序号,选择计算的方法:";
int k;
cin >> k;
//得出算法运行时间
double ret;
clock_t start = clock();//调取开始操作时系统时间
switch (k)
{
case 1:
for (int i = 0; i < n; i++)
{
int a = Zhan_Zhuan(p[i][0], p[i][1]);
}
break;
case 2:
for (int i = 0; i < n; i++)
{
int a = Qiong_Ju(p[i][0], p[i][1]);
}
break;
case 3:
for (int i = 0; i < n; i++)
{
int a = Geng_Xiang(p[i][0], p[i][1]);
}
break;
case 4:
for (int i = 0; i < n; i++)
{
int a = Stein(p[i][0], p[i][1]);
}
break;
default:
cout << "序号错误!" << endl;
break;
}
if(k<=4&&k>=1)
{
clock_t stop = clock();//调取结束操作时系统时间
ret = (double)(stop - start);
cout << "算法运行时间:" << ret << "ms";
}
cout << endl;
cout << "继续吗,(y/n):"<<endl;
ch = getchar();
ch = getchar();
} while (ch == 'y'||ch=='Y');
/*释放动态存储空间*/
delete[]p;
system("pause");
}
/**
* 文件名:algorithm.h
* 描述:包含求最大公约数的四种算法的函数声明
* 函数列表:
1.Zhan_Zhuan();//辗转相除法
2.Qiong_Ju(); //穷举法
3.Geng_Xiang();//更相减损法
4.Stein(); //Stein算法
**/
#pragma once
#ifndef ALGORITHM_H
#define ALGORITHM_H
int Zhan_Zhuan(int, int);
int Qiong_Ju(int, int);
int Geng_Xiang(int, int);
int Stein(int, int);
#endif
/**
* 文件名:algorithm.cpp
* 描述:包含对应函数定义
* 函数列表:
1.Zhan_Zhuan();//辗转相除法
2.Qiong_Ju(); //穷举法
3.Geng_Xiang();//更相减损法
4.Stein(); //Stein算法
**/
#include "algorithm.h"
/**
* 描述:辗转相除法
传值给a, b开始求两个数的最大公约数,结果作为函数返回值输出
**/
int Zhan_Zhuan(int a, int b)
{
{
int temp; /*定义整型变量*/
if (a < b) /*通过比较求出两个数中的最大值和最小值*/
{
temp = a; a = b; b = temp;
} /*设置中间变量进行两数交换*/
while (b != 0) /*通过循环求两数的余数,直到余数为0*/
{
temp = a % b;
a = b; /*变量数值交换*/
b = temp;
}
return (a); /*返回最大公约数到调用函数处*/
}
}
/**
* 描述:穷举法
传值给a, b开始求两个数的最大公约数,结果作为函数返回值输出
**/
int Qiong_Ju(int a, int b)
{
int temp; /*定义义整型变量*/
temp = (a > b) ? b : a; /*采种条件运算表达式求出两个数中的最小值*/
while (temp > 0)
{
if (a%temp == 0 && b%temp == 0) /*只要找到一个数能同时被a,b所整除,则中止循环*/
break;
temp--; /*如不满足if条件则变量自减,直到能被a,b所整除*/
}
return (temp); /*返回满足条件的数到主调函数处*/
}
/**
* 描述:更相减损法
传值给a, b开始求两个数的最大公约数,结果作为函数返回值输出
**/
int Geng_Xiang(int a, int b)
{
int ans = 1;//储存第一步中约掉的若干个2
int gcd;//储存最终返回的结果
while (a % 2 == 0 && b % 2 == 0)//如果a,b均为偶数则用2约简
{
a /= 2;
b /= 2;
ans *= 2;
}
while (a != b)//判断两数是否相等,相等则得出最大约数
{
if (a > b)
a -= b;//以较大的数减较小的数
else
b -= a;//以较大的数减较小的数
}
gcd = a * ans; //求第一步中约掉的若干个2与第二步中等数的乘积
return gcd;
}
/**
* 描述:Stein算法
传值给a, b开始求两个数的最大公约数,结果作为函数返回值输出
**/
int Stein(int x, int y)
{
int factor = 0;
int temp;
if (x < y)
{
temp = x;
x = y;
y = temp;
}
if (0 == y)
{
return 0;
}
while (x != y)
{
if (x & 0x1)
{/* when x is odd */
if (y & 0x1)
{/* when x and y are both odd */
y = (x - y) >> 1;
x -= y;
}
else
{/* when x is odd and y is even */
y >>= 1;
}
}
else
{/* when x is even */
if (y & 0x1)
{/* when x is even and y is odd */
x >>= 1;
if (x < y)
{
temp = x;
x = y;
y = temp;
}
}
else
{/* when x and y are both even */
x >>= 1;
y >>= 1;
++factor;
}
}
}
return (x << factor);
}
四、运行结果
五、总结
一个完整的程序设计环节是环环相扣的,问题分析,用文字将步骤完整的描述出来,对我个人而言,这步工作能够保证整个编程过程清晰明确,接着测试,调试,步步相辅,最终得到结果。
过程中,了解到灵活使用位运算符有时候会带来很好的效果,利用new动态分配存储空间达到创建动态数组的目的。