算法实验一实验报告.docx
《算法实验一实验报告.docx》由会员分享,可在线阅读,更多相关《算法实验一实验报告.docx(25页珍藏版)》请在冰豆网上搜索。
算法实验一实验报告
武汉轻工大学
数学与计算机学院
算法分析实验报告
指导老师:
汤小月
专业:
信息管理与信息系统
班级:
信管1201班
学号:
姓名:
实验一分治与递归(2学时)
基本题一:
基本递归算法
一、实验目的与要求
1、熟悉C/C++语言的集成开发环境;
2、通过本实验加深对递归过程的理解
二、实验内容:
掌握递归算法的概念和基本思想,分析并掌握“整数划分”问题的递归算法。
三、实验题
任意输入一个整数,输出结果能够用递归方法实现整数的划分。
具体程序代码如下:
#include
usingnamespacestd;
intq(intn,intm)//正整数n的最大加数m的划分数
{
if((n<1)||(m<1))return0;//n,m需>1
if((n==1)||(m==1))return1;//正整数或者最大加数=1时,只有一种划分情况
if(nif(n==m)returnq(n,m-1)+1;//递归,n的划分由其q(n,m-1)和n1=n组成
returnq(n,m-1)+q(n-m,m);//正整数n的最大加数n1不大于m的划分由n1=m的划分和n1=m-1的划分组成
}
voidmain()
{
intn,m;
cout<<"请输入一个整数n(-1退出):
"<cin>>n;
while(n>=1)
{
cout<<"请输入一个最大加数m:
"<cin>>m;
cout<<"正整数n的最大加数m的划分数为"<cout<<"请输入一个整数n(-1退出):
"<cin>>n;
}
}
进行编译如下:
运行结果如下:
四、实验步骤
1.理解算法思想和问题要求;
2.编程实现题目要求;
3.上机输入和调试自己所编的程序;
4.验证分析实验结果;
5.整理出实验报告。
基本题二:
棋盘覆盖问题
一、实验目的与要求
1、掌握棋盘覆盖问题的算法;
2、初步掌握分治算法
二、实验题:
盘覆盖问题:
在一个2k×2k个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。
在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
三、实验提示
voidchessBoard(inttr,inttc,intdr,intdc,intsize)
{
if(size==1)return;
intt=tile++, //L型骨牌号
s=size/2; //分割棋盘
//覆盖左上角子棋盘
if(dr
//特殊方格在此棋盘中
chessBoard(tr,tc,dr,dc,s);
else{//此棋盘中无特殊方格
//用t号L型骨牌覆盖右下角
board[tr+s-1][tc+s-1]=t;
//覆盖其余方格
chessBoard(tr,tc,tr+s-1,tc+s-1,s);}
//覆盖右上角子棋盘
if(dr
|
=tc+s) //特殊方格在此棋盘中
chessBoard(tr,tc+s,dr,dc,s);
else{//此棋盘中无特殊方格
//用t号L型骨牌覆盖左下角
board[tr+s-1][tc+s]=t;
//覆盖其余方格
chessBoard(tr,tc+s,tr+s-1,tc+s,s);}
//覆盖左下角子棋盘
if(dr>=tr+s&&dc //特殊方格在此棋盘中
chessBoard(tr+s,tc,dr,dc,s);
else{//用t号L型骨牌覆盖右上角
board[tr+s][tc+s-1]=t;
//覆盖其余方格
chessBoard(tr+s,tc,tr+s,tc+s-1,s);}
//覆盖右下角子棋盘
if(dr>=tr+s&&dc>=tc+s)
//特殊方格在此棋盘中
chessBoard(tr+s,tc+s,dr,dc,s);
else{//用t号L型骨牌覆盖左上角
board[tr+s][tc+s]=t;
//覆盖其余方格
chessBoard(tr+s,tc+s,tr+s,tc+s,s);}
}
编写程序代码如下:
#include
usingnamespacestd;
intboard[65][65],tile;/*tile为纸片编号*/
voidchessBoard(inttr,inttc,intdr,intdc,intsize)
{
if(size==1)return;
intt=tile++,//L型骨牌号
s=size/2;//分割棋盘
//覆盖左上角子棋盘
if(dr
//特殊方格在此棋盘中
chessBoard(tr,tc,dr,dc,s);
else{//此棋盘中无特殊方格
//用t号L型骨牌覆盖右下角
board[tr+s-1][tc+s-1]=t;
//覆盖其余方格
chessBoard(tr,tc,tr+s-1,tc+s-1,s);}
//覆盖右上角子棋盘
if(dr
|
=tc+s)//特殊方格在此棋盘中
chessBoard(tr,tc+s,dr,dc,s);
else{//此棋盘中无特殊方格
//用t号L型骨牌覆盖左下角
board[tr+s-1][tc+s]=t;
//覆盖其余方格
chessBoard(tr,tc+s,tr+s-1,tc+s,s);}
//覆盖左下角子棋盘
if(dr>=tr+s&&dc//特殊方格在此棋盘中
chessBoard(tr+s,tc,dr,dc,s);
else{//用t号L型骨牌覆盖右上角
board[tr+s][tc+s-1]=t;
//覆盖其余方格
chessBoard(tr+s,tc,tr+s,tc+s-1,s);}
//覆盖右下角子棋盘
if(dr>=tr+s&&dc>=tc+s)
//特殊方格在此棋盘中
chessBoard(tr+s,tc+s,dr,dc,s);
else{//用t号L型骨牌覆盖左上角
board[tr+s][tc+s]=t;
//覆盖其余方格
chessBoard(tr+s,tc+s,tr+s,tc+s,s);}
}
//输出最终的结果
voidresult(intb[][65],intn){
inti,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
cout<
cout<}
}
intmain(){
intsize,dr,dc;
cout<<"选择输入4种不同形态的L型骨牌中的一种(4/8/16/64):
"<cin>>size;
cout<<"请输入特殊的块的位置(x,y):
"<cin>>dr>>dc;
cout<<"结果如下:
"<board[dr][dc]=-1;
tile++;
chessBoard(1,1,dr,dc,size);
result(board,size);
}
运行调试结果如下:
试运行结果如下:
提高题一:
二分搜索
一、实验目的与要求
1、熟悉二分搜索算法;
2、初步掌握分治算法;
二、实验题
1、设a[0:
n-1]是一个已排好序的数组。
请改写二分搜索算法,使得当搜索元素x不在数组中时,返回小于x的最大元素的位置I和大于x的最小元素位置j。
当搜索元素在数组中时,I和j相同,均为x在数组中的位置。
2、设有n个不同的整数排好序后存放于t[0:
n-1]中,若存在一个下标I,0≤i<n,使得t[i]=i,设计一个有效的算法找到这个下标。
要求算法在最坏的情况下的计算时间为O(logn)。
三、实验提示
1、用I,j做参数,且采用传递引用或指针的形式带回值。
boolBinarySearch(inta[],intn,intx,int&i,int&j)
{
intleft=0;
intright=n-1;
while(left {
intmid=(left+right)/2;
if(x==a[mid])
{
i=j=mid;
returntrue;
}
if(x>a[mid])
left=mid+1;
else
right=mid-1;2
}
i=right;
j=left;
returnfalse;
}
intSearchTag(inta[],intn,intx)
{
intleft=0;
intright=n-1;
while(left {
intmid=(left+right)/2;
if(x==a[mid])returnmid;
if(x>a[mid])
right=mid-1;
else
left=mid+1;
}
return-1;
}
实验题1代码编写如下:
#include
usingnamespacestd;
voidBubbleSort(int*pData,intCount)
//冒泡排序的函数,pData中从0位置处存了Count个数,该函数将数组中元素排序
{
intiTemp;
for(inti=1;i{
for(intj=Count-1;j>=i;j--)
{
if(pData[j]{
iTemp=pData[j-1];
pData[j-1]=pData[j];
pData[j]=iTemp;
}
}
}
}
boolBinarySearch(inta[],intn,intx,int&i,int&j)
//数组a大小为n,数组中存放了已经排好序(升序)的数列
{
intleft=0;
intright=n-1;
intmid=0;
while(left{
mid=(left+right)/2;
if(x==a[mid])
{
i=j=mid;
returntrue;
}
if(x>a[mid])
left=mid+1;
else
right=mid-1;
}
i=right;
j=left;
returnfalse;
}
intSearchTag(inta[],intn,intx)
{
intleft=0;
intright=n-1;
while(left{
intmid=(left+right)/2;
if(x==a[mid])
returnmid;
if(x>a[mid])
right=mid-1;
else
left=mid+1;
}
return-1;
}
intmain()
{
inta[100];
cout<<"请输入数组中数的个数,小于100:
";
intnum=0;
cin>>num;
cout<<"请输入数组中的数:
"<for(inti=0;icin>>a[i];
//下面将数组a排成升序
BubbleSort(a,num);
cout<<"下面输出排序后的数组:
"<for(i=0;iprintf("%4d",a[i]);
cout<cout<<"请输入要查找的数:
";
intx=0;
cin>>x;
intj=0;
if(BinarySearch(a,num,x,i,j))
cout<<"找到了,位置为"<
else
cout<<"没找到,小于该数的最大元素位置为"<
return0;
}
试运行调试结果如下:
运行结果如下图所示:
实验题2编写代码如下:
#include
usingnamespacestd;
/*根据题目中的隐含要求,现在将问题进行简化,假设数组中存放的数全部为整数*/
voidBubbleSort(int*pData,intCount)
//冒泡排序的函数,pData中从0位置处存了Count个数,该函数将数组中元素排升序
{
intiTemp;
for(inti=1;i{
for(intj=Count-1;j>=i;j--)
{
if(pData[j]{
iTemp=pData[j-1];
pData[j-1]=pData[j];
pData[j]=iTemp;
}
}
}
}
boolBinaryFind_iei(inta[],intn,int&i)
//数组a大小为n,数组中存放了已经排好序(升序)的数列
{
intleft=0;
intright=n-1;
intmid=0;
while(left{
mid=(left+right)/2;
if(mid==a[mid])
{
i=mid;
returntrue;
//找到了
}
else
if(mid>a[mid])
left=mid;
else
right=mid;
}
returnfalse;
}
intmain()
{
inta[100];
cout<<"请输入数组中数的个数,小于100:
";
intnum=0;
cin>>num;
cout<<"请输入数组中的数:
"<for(intii=0;iicin>>a[ii];
//下面将数组a排成升序
BubbleSort(a,num);
cout<<"下面输出排序后的数组:
"<for(inti=0;iprintf("%4d",a[i]);
cout<intj=0;
if(BinaryFind_iei(a,num,j))
cout<<"找到了,位置为"<else
cout<<"不存在符合第i个位置等于i的元素。
"<return0;
}
试运行调试结果如下:
运行结果如下:
结果分析:
利用分治策略求解时,所需时间取决于分解后子问题的个数、子问题的规模大小等素,而二分法,由于其划分的简单和均匀的特点,是经常采用的一种有效的方法,例如二分法检索。
提高题二:
用分治法实现元素选择
一、实验要求与目的
1、了解分治法的基本思想,掌握递归程序编写方法;
2、使用分治法编程,求解线形序列中第k小元素。
二、实验内容
1、给定线形序列集中n个元素和一个整数k,1≤k≤n,输出这n个元素中第k小元素的值及其位置。
2、简述该算法的原理、步骤。
对该算法与直接排序查找进行比较。
3、编写并调试程序。
测试要求:
元素个数不少于100;分三种情况:
k=1、k=n和k=中位数。
编写程序代码如下所示:
#include
#include
#include
#include
intpartition(inta[],intp,intr)
{
intz=p,x=r+1;
inty=a[p];
intt;
while
(1)
{
while(a[++z]while(a[--x]>y);
if(z>=x)break;
t=a[z];
a[z]=a[x];
a[x]=t;
}
a[p]=a[x];
a[x]=y;
returnx;
}
voidquicksort(inta[],intp,intr)
{
intq;
if(p{
q=partition(a,p,r);
quicksort(a,p,q-1);
quicksort(a,q+1,r);
}
}
intmain()
{
for(;;)
{
intk,*a,*b,n,i,d,s;
printf("请输入数组个数:
");
scanf("%d",&n);
printf("\n");
a=(int*)malloc(sizeof(int)*n);//给数组a分配空间
srand((unsigned)time(NULL));
b=(int*)malloc(sizeof(int)*n);//给数组b分配空间
srand((unsigned)time(NULL));
for(i=0;i{
a[i]=rand()%100+1;//产生小于100的数据
}
for(i=0;i{
printf("%d\t",a[i]);
if((i+1)%10==0)//每行10个数据
printf("\n");
}
printf("\n");
for(i=0,d=0;d{
b[d]=a[i];
i++;
}
quicksort(a,0,i-1);//调用快速排序进行排序
printf("排序后");
printf("\n");
for(i=0;i{
printf("%d\t",a[i]);
if((i+1)%10==0)//输出排好序的数组a,每行10个数据
printf("\n");
}
printf("\n");
printf("请输入第k小元素:
");
scanf("%d",&k);
for(d=0;d{
if(b[d]==a[k-1])//从数组b中找出第k小的数在原数组中的位置
s=d+1;
}
printf("第%d小元素为:
%d",k,a[k-1]);
printf("\n");
printf("第%d小元素位置为:
%d",k,s);
printf("\n");
system("pause");
printf("\n");
}
}
试运行调试结果如下:
运行结果如下:
测试一:
K=1
测试二:
K=n(此处为K=n=102)
测试三:
k=中位数
五:
实验总结
通过此次实验进一步熟悉了C/C++语言的集成开发环境以及进一步加深了对递归过程的理解,理论结合实际让自己对此阶段的知识掌握的更加牢固,收益颇丰。
展开阅读全文
相关搜索
资源标签