算法设计综合实验报告.docx
《算法设计综合实验报告.docx》由会员分享,可在线阅读,更多相关《算法设计综合实验报告.docx(30页珍藏版)》请在冰豆网上搜索。
![算法设计综合实验报告.docx](https://file1.bdocx.com/fileroot1/2023-8/14/0fbea05e-e595-4516-b475-a62187cf5e3c/0fbea05e-e595-4516-b475-a62187cf5e3c1.gif)
算法设计综合实验报告
院系:
计算机科学学院
专业:
计算机科学与技术
年级:
2008
课程名称:
算法设计与分析基础
班号:
计科一班
组号:
32
指导教师:
2010年12月10日
组员
学号
姓名
实验名称
算法实验主菜单的设计
实验室
9#203
实
验
目
的
或
要
求
实验目的:
1)熟悉实验环境VC++6.0;
2)复习C、C++语言以及数据结构课程的相关知识,实现课程间的平滑过度;
实验要求:
1)设计的主菜单可以是图形模式的,也可以是控制台模式的。
以控制台为例,主菜单大致如下:
-------------------------
《算法设计与分析》实验
-------------------------
1.算法分析基础——Fibonacci序列问题
2.分治法在数值问题中的应用——最近点对问题
3.减治法在组合问题中的应用——8枚硬币问题
4.变治法在排序问题中的应用——堆排序问题
5.动态规划法在图问题中的应用——全源最短路径问题
99.退出本实验
-------------------------
请输入您所要执行的操作(1,2,3,4,5,99):
2)点击操作后进入相应的实验项目或是相应项目的下一级菜单;
3)可以反复执行,直到退出实验。
实
验
原
理
(
算
法
基
本
思
想
)
构造menu函数,以菜单形式输出控制界面(按需求分析要求);
构造switch(start)函数,控制各个子程序,以解决各个问题:
switch(start)
{
case1:
{}break;
case2:
{}break;
case3:
{}break;
case4:
{}break;
case5:
{}break;
case99:
return-1;
default:
printf("输入有误!
");
}
程
序
代
码
voidmenu()
{
printf("\n\n-----------------------------------------------------------");
printf("\n《算法设计与分析》实验");
printf("\n------------------------------------------------------------");
printf("\n1.算法分析基础——Fibonacci序列问题");
printf("\n2.分治法在数值问题中的应用——最近点对问题");
printf("\n3.减治法在组合问题中的应用——8枚硬币问题");
printf("\n4.变治法在排序问题中的应用——堆排序问题");
printf("\n5.动态规划法在图问题中的应用——全源最短路径问题");
printf("\n99.退出本实验");
printf("\n-------------------------------------------------------------------");
printf("\n请输入您所要执行的操作(1,2,3,4,5,99):
");
}
intmain()
{
intstart;
for(;;)
{
menu();
scanf("%d",&start);
switch(start)
{
case1:
{
system("cls");
printf("----------实验一.Fibonacci序列问题----------\n\n");
Fib();
fflush(stdin);
}break;
case2:
{
system("cls");
printf("----------实验二.最近点对问题----------\n");
closestPath();
fflush(stdin);
}break;
case3:
{
system("cls");
printf("----------实验三.8枚硬币问题----------\n");
Coins();
fflush(stdin);
}break;
case4:
{
system("cls");
printf("----------实验四.堆排序问题----------\n");
heapsort();
fflush(stdin);
}break;
case5:
{
system("cls");
printf("----------实验五.全源最短路径问题----------\n");
fflush(stdin);
}break;
case99:
return-1;
default:
printf("输入有误!
");
}
实
验
结
果
及
分
析
实验结果如下:
实现了以菜单形式的显示格式,清晰明了;
用户选择相应操作以解决相应问题;
实验名称
计算第n个斐波那契数
实验室
9#203
实
验
目
的
或
要
求
实验目的
1)理解递归算法和迭代算法的设计思想以及递归程序的调式技术
2)掌握并应用递归算法和迭代算法效率的理论分析(前验分析)和实际分析(后验分析)方法;
3)理解这样一个观点:
不同的算法可以解决相同的问题,这些算法的解题思路不同,复杂程度不同,效率也不同;
实验要求
1)使用教材2.5节中介绍的迭代算法Fib(n),找出最大的n,使得第n个Fibonacci数不超过计算机所能表示的最大整数,并给出具体的执行时间;
2)对于要求1),使用教材2.5节中介绍的递归算法F(n)进行计算,同样给出具体的执行时间,并同1)的执行时间进行比较;
3)对于输入同样的非负整数n,比较上述两种算法基本操作的执行次数;
4)对1)中的迭代算法进行改进,使得改进后的迭代算法其空间复杂度为Θ
(1);
5)设计可供用户选择算法的交互式菜单(放在相应的主菜单下)。
实
验
原
理
(
算
法
基
本
思
想
)
实验分别用递归算法和迭代算法求解,并对两种算法的运行时间进行比较;
递归算法:
设f(n)为斐波那契数列的第n个数。
那么有递归式f(n)=f(n-1)+f(n-2)。
按照这个朴素的递归思想可以得出结论。
但是时间复杂度是O(2^n),计算缓慢,解决不了大规模问题。
迭代算法
:
求解fib(n),把它推到求解fib(n-1)和fib(n-2)。
也就是说,为计算fib(n),必须先计算fib(n-1)和fib(n-2),而计算fib(n-1)和fib(n-2),又必须先计算fib(n-3)和fib(n-4)。
依次类推,直至计算fib
(1)和fib(0),分别能立即得到结果1和0。
迭代算法消除了大量重复的计算,效率上有了大幅提高。
程
序
代
码
unsignedlongF_RE(intn)
{
if(n==1)return0;
if(n==2)return1;
if(n>2)return(F_RE(n-1)+F_RE(n-2));
}
unsignedlongF_ITER(intn)
{unsignedlongf1=1,f2=1,fn;
if(n<=1)return0;
if(n==2||n==3)return1;
for(inti=4;i<=n;i++)
{
fn=f1+f2;
f1=f2;
f2=fn;
}
returnfn;
}
voidF_MAX(unsignedlongf,intn)
{
unsignedlongTemp,max;
max=pow(2,31)-1;//printf("%ld",max);
while(f<=max){
Temp=f;
n++;
f=F_ITER(n);
}
printf("\n\n不超出该32位计算机所能表示的最大整数\n及其所在序列中的位置为(%ld,%d)\t",Temp,n-1);
}
voidFib()
{unsignedlongF_i;
inti=0;
charch;
printf("选择输出第N个斐波拉契数:
\n");
printf("1.迭代算法;\n2.递归算法\t");
fflush(stdin);
ch=getchar();
if(ch=='1'){
printf("\n需要输出第几个数(1-50)?
\t");
scanf("%d",&i);
F_i=F_ITER(i);
printf("%ld\t",F_i);
F_MAX(F_i,i);
}
elseif(ch=='2'){
printf("\n需要输出第几个数(1-50)?
\t");
scanf("%d",&i);
F_i=F_ITER(i);
printf("%ld\t",F_RE(i));
F_MAX(F_i,i);
}
elseprintf("\n输入有误!
");
}
实
验
结
果
及
分
析
输出结果如下:
迭代算法
递归算法
递归算法在n超过20,效率低的缺点显露无疑;迭代法的优势就体现出来了。
实验名称
平面最近点问题
实验室
9#203
实
验
目
的
或
要
求
实验目的
1)提高应用蛮力法设计算法的技能;
2)深刻理解并掌握分治法的设计思想;
3)理解这样一个观点:
用蛮力法设计的算法,一般来说,经过适度的努力后,都可以对其进行改进,以提高算法的效率。
实验要求
1)设计并实现用BF方法求解最近点对问题的算法;
2)设计并实现用DAC方法求解最近点对问题的算法;
3)以上两种算法的输入既可以手动输入,也可以自动生成;
4)算法不仅要输出最近点对的距离,还要输出最近点对的两个点;
5)对上述两个算法进行时间复杂性分析,并设计实验程序验证分析结果;
6)设计可供用户选择算法的交互式菜单(放在相应的主菜单下)
实
验
原
理
(
算
法
基
本
思
想
)
分治法
已知集合S中有n个点,分治法的思想就是将S进行拆分,分为2部分求最近点对。
算法每次选择一条垂线L,将S拆分左右两部分为SL和SR,L一般取点集S中所有点的中间点的x坐标来划分,这样可以保证SL和SR中的点数目各为n/2,
(否则以其他方式划分S,有可能导致SL和SR中点数目一个为1,一个为n-1,不利于算法效率,要尽量保持树的平衡性)
依次找出这两部分中的最小点对距离:
δL和δR,记SL和SR中最小点对距离δ=min(δL,δR),如图1:
对于SL虚框范围内的p点,在SR虚框中与p点距离小于δ的顶多只有六个点,就是图二右图中的2个正方形的6的顶点。
这个可以反推证明,如果右边这2个正方形内有7个点与p点距离小于δ,例如q点,则q点与下面正方形的四个顶点距离小于δ,则和δ为SL和SR中的最小点对距离相矛盾。
因此对于SL虚框中的p点,不需求出p点和右边虚线框内所有点距离,只需计算SR中与p点y坐标距离最近的6个点,就可以求出最近点对,节省了比较次数。
程
序
代
码
structnode
{intx_value;
inty_value;
doubleshortest_distance;
intresult_x_value;
intresult_y_value;
};
int*PARTITION(structnode*A,intstart,intend,intkey)
{
if(key==1)//按x排序
{
int*partition;
partition=newint;
doublex=A[end].x_value;
inti=start-1;
for(intj=start;j{
if(A[j].x_value<=x)
{
i++;
structnodetant=A[i];
A[i]=A[j];
A[j]=tant;
}
}
structnodetant=A[i+1];
A[i+1]=A[end];
A[end]=tant;
*partition=i+1;
returnpartition;
}
else//按y排序
{
int*partition;
partition=newint;
doubley=A[end].y_value;
inti=start-1;
for(intj=start;j{
if(A[j].y_value<=y)
{
i++;
structnodetant=A[i];
A[i]=A[j];
A[j]=tant;
}
}
structnodetant=A[i+1];
A[i+1]=A[end];
A[end]=tant;
*partition=i+1;
returnpartition;
}
}
voidquick_sort(structnode*A,intstart,intend,intkey)//可以根据x和y对结构体数组排序
{
if(end>start)
{
int*partition;
partition=newint;
partition=PARTITION(A,start,end,key);
quick_sort(A,start,*partition-1,key);
quick_sort(A,*partition,end,key);
}
}
voidcombine(structnode*A,structnode*result1,structnode*result2,structnode*result,intstart,intmiddle,intend)//合并两个部分的结果
{
doublemin_distance;
intn=end-start;
intlength=0;
intj,k;
structnodetant[100];//用以保存x_value在[middle-min_distance,middle+min_distance]的点
doublebelow,above;//below和above分别为[middle-min_distance,middle+min_distance]的上界和下界
intkeyword;
if(result1->shortest_distance>result2->shortest_distance)//寻找最小值
{result->x_value=result2->x_value;
result->y_value=result2->y_value;
result->result_x_value=result2->result_x_value;
result->result_y_value=result2->result_y_value;
result->shortest_distance=result2->shortest_distance;
min_distance=result2->shortest_distance;
}
else
{
result->x_value=result1->x_value;
result->y_value=result1->y_value;
result->result_x_value=result1->result_x_value;
result->result_y_value=result1->result_y_value;
result->shortest_distance=result1->shortest_distance;
min_distance=result1->shortest_distance;//min_distance=min{result1.shortes_distance,result2.shortest_distance}
}
below=A[middle].x_value-min_distance;
above=A[middle].x_value+min_distance;
for(inti=0;i<=n;i++)
if(A[i].x_value>=below&&A[i].x_value<=above)
tant[length++]=A[i];//构造临时数组,即x_value在[middle-min_distance,middle+min_distance]的点
keyword=2;
length--;
quick_sort(tant,0,length,keyword);
//按y对tant数组排序
for(k=0;k<=length+1;k++)
{
j=k+1;
while(j<=length&&(tant[j].y_value-tant[k].y_value<=min_distance||tant[k].y_value-tant[j].y_value<=min_distance))//?
?
2miin_distance
{
doubletant_distance;
doubletemp=(double)((tant[k].x_value-tant[j].x_value)*(tant[k].x_value-tant[j].x_value)+(tant[k].y_value-tant[j].y_value)*(tant[k].y_value-tant[j].y_value));
tant_distance=sqrt(temp);
if(tant_distance<=min_distance)
{
result->x_value=tant[k].x_value;
result->y_value=tant[k].y_value;
result->result_x_value=tant[j].x_value;
result->result_y_value=tant[j].y_value;
result->shortest_distance=tant_distance;
min_distance=tant_distance;
}
j++;
}
}
}
voidshortest_distance(structnode*A,structnode*result,intstart,intend)
{
if(end-start>2)
{
intmiddle;
structnode*result1=newstructnode;
structnode*result2=newstructnode;
//structnode*final_result=newstructnode;
result1->shortest_distance=1000000;
result2->shortest_distance=1000000;//初始化结果result1,result2
middle=(start+end)/2;
shortest_distance(A,result1,start,middle);
shortest_distance(A,result2,middle+1,end);
combine(A,result1,result2,result,start,middle,end);
}
else//分组内点数不足3个,直接得结果
{
for(inti=start;i<=end;i++)
for(intk=i+1;k<=end;k++)
{
doubletant_distance;
doubletemp=(double)((A[i].x_value-A[k].x_value)*(A[i].x_value-A[k].x_value)+(A[i].y_value-A[k].y_value)*(A[i].y_value-A[k].y_value));
tant_distance=sqrt(temp);
if(tant_distance<=result->shortest_distance)
{
result->x_value=A[i].x_value;
result->y_value=A[i].y_value;
result->result_x_value=A[k].x_value;
result->result_y_value=A[k].y_value;
result->shortest_distance=tant_distance;
}
}
}
}
voidclosestPath()
{