本文已参与「新人创作礼」活动,一起开启掘金创作之路。
【算法】蛮力法分析及实现
一、目的
了解影响程序运行时间的主要因素;掌握渐近时间复杂度的表示方法;掌握递归程序的时间复杂度计算。
二、实验内容
实验要求:先用伪代码或流程图描述利用蛮力法解决的算法解决方案,再用程序实现,计算时间复杂度,记录最终测试数据和测试结果。
2.1实验内容:
2.1.1 求a的n次方或者求n个自然数的和或者计算n的阶乘
2.1.2 顺序查找(改写课本例子,将哨兵放在尾部)
2.1.3 求两个自然数的最大公约数或分式化简
2.1.4一维最近对问题
2.2.5 TSP问题或哈密顿问题
2.2.6 二维最近对问题或者凸包问题
2.2.7 n个数的列表的第k个最小元素的问题
2.2.8 0/1背包问题
三、设计和编码
3.1算法设计
3.1.1计算n的阶乘伪代码 Begin
- int jiechen(int n){
1.1. if(n==1)
1.2. 返回1;
1.3. 否则返回n*jiechen(n-1)的值;
} - int main (){
2.1. int a;
2.2. 输入a;
2.3. 输出jiechen(a)的结果;
2.4. return 0;
}
End 3.1.2顺序查找伪代码
Begin - int seqsearch(int r[],int n,int k){
1.1. int i=0;
1.2. 设置哨兵到末尾;
1.3. i从0开始直至遍历最后一位数;
1.4. 循环结束时返回i+1的值;
}
2.int main(){
2.1. int a[100];
2.2. int n,i,first,num;
2.3. 输入n;
2.4. 输入数组a;
2.5. 调用函数seqsearch处理;
2.6. 如果函数返回值为n则查找成功;
2.7. 否则查找失败;
}
End
3.1.3求两个自然数的最大公约数伪代码 Begin
1.int main(){
1.1. int a,b,c;
1.2. 输入a、b;
1.3. a大于b则c等于a;
1.4. 反之c等不b;
1.5. a,b同时能被c整除不循环,否则c--;
1.6. 输出最大公约数c;
}
End
3.1.4一维最近对问题伪代码
Bbegin
1.int closestPoints(int x[],int y[],int n){
1.1. 定义最近点的下标;
1.2. 在i小于j的点对情况下计算欧几里得距离;
1.3. 循环计算所有点,输出距离最小的两点;
}
2.int main(){
2.1. int x[100],y[100];
2.2. 输入x、y坐标;
2.3. closestPoints(x,y,n)输出结果;
}
End
3.1.5 TSP问题分析
首先选择第一个城市作为出发点,从当前节点出发遍历所有能达到的下一节点后,选择距离最近的点作为下一节点,然后把当前节点标记为已走过,下一节点作为当前节点,重复贪心策略,以此类推直至所有节点都标记为已走节点,最后回到出发点结束。
3.1.6 二维最近对问题分析
首先将点集按照横坐标排序,根据其中心点将点集一分为二,构成最小距离的两个点要么同时在左边的子点集,要么同时在右边的子点集,或者一个在左边一个在右边。前两种情况可以递归解决,主要根据第三种情况分析即可得出结果。
3.1.7 0/1背包问题分析
首先将原问题分解为子问题,接着确定状态即是否翻入物品,然后确定一些初始状态的值,最后得出如何从一个或多个已知状态求出另一个未知状态的值。
3.2程序代码
3.2.1.计算n的阶乘
#include<stdio.h>
int jiechen(int n){
if(n==1)
return 1;
return n*jiechen(n-1);
}
int main (){
int a;
printf("请输入待求的阶层数:");
scanf("%d",&a);
printf("结果为:%d\n",jiechen(a));
return 0;
}
3.2.2.顺序查找
#include<stdio.h>
int seqsearch(int r[],int n,int k){
int i=0;
while(r[i] != k)//设置哨兵到末尾
i++;
return i+1;
}
int main(){
int a[100];
int n,i,first,num;
printf("请输入数的个数:");
scanf("%d",&n);
printf("请输入具体数字:");
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
num = seqsearch(a,n,a[n-1]);
if(num==n)
printf("查找成功!");
else
printf("查找失败!");
}
3.2.3.求两个自然数的最大公约数
#include<stdio.h>
int main(){
int a,b,c;
printf("输入两个数字:");
scanf("%d%d",&a,&b);
if(a>b)
c=b;
else
c=a;
while(a%c!=0||b%c!=0)//a,b同时能被c整除不执行该循环
c--;
printf("最大公约数为;%d\n",c);
}
3.2.4.一维最近对问题
#include<stdio.h>
int closestPoints(int x[],int y[],int n){
int index1,index2;
int d,minDist=1000;
for(int i=0;i<n-1;i++)
for(int j=i+1;j<n;j++){
d=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
if(d<minDist){
minDist=d;
index1=i;index2=j;
}
}
printf("最近的点对是第%d和第%d个点",index1+1,index2+1);
return minDist;
}
int main()
{
int x[100],y[100];
int n,i,first,num;
printf("请输入点的个数:");
scanf("%d",&n);
printf("请输入各点的x坐标:");
for(i=0;i<n;i++){
scanf("%d",&x[i]);
}
printf("请输入各x坐标所对应的y坐标:");
for(i=0;i<n;i++){
scanf("%d",&y[i]);
}
closestPoints(x,y,n);
}
四、运行结果及分析
4.1运行结果
4.1.1计算n的阶乘运算结果
时间复杂度:O(n)
4.1.2顺序查找运算结果
时间复杂度:O(n)
4.1.3求两个自然数的最大公约数运算结果
时间复杂度:O(n)
4.1.4一维最近对问题运算结果
时间复杂度:O(n)
4.2分析
冒泡法排序相对来说比选择法简单,由于冒泡法每次都要交换元素的顺序,而选择法则只需要记录元素的下标,因此冒泡法效率较低。对于数据较小的数组,运用冒泡法足以胜任,对于数据较大的数组,选择法排序的效率会明显提高。而快速排序法故名思义是目前最快的排序法,但是不够冒泡排序法稳定。
五、实验小结
我们分析并解决了所有必做任务,及选做任务中的2.2.6,并且对选做任务中的多个算法进行了简易的分析。计算出来所做任务程序的时间复杂度。可以很显然的看到各个方法的计算效率,从而对各个算法进行分析比较,评估出各算法的利弊之处。 在实验过程中,由于能力不够,对于选做任务未能全部完成,但仍然尽力作出部分内容。并且通过网络工具获取一些TSP问题、0/1背包问题等问题的程序代码进行分析,对其算法进行较为深入的了解。最后结合课本更深入的对蛮力法进行了学习。