算法分析与设计实验报告.docx
《算法分析与设计实验报告.docx》由会员分享,可在线阅读,更多相关《算法分析与设计实验报告.docx(19页珍藏版)》请在冰豆网上搜索。
算法分析与设计实验报告
算法分析与设计
实验报告
目录
实验一:
递归与分治………………………………………1
二分查找
归并排序
快速排序
实验二:
回溯算法…………………………………………8
0—1背包
实验三:
动态规划…………………………………………12
矩阵连乘最少乘法数
实验一:
递归与分治
一、实验目的
理解递归算法的思想和递归程序的执行过程,并能熟练编写递归程序。
掌握分治算法的思想,对给定的问题能设计出分治算法予以解决。
二、实验内容
1.二分查找
在对线性表的操作中,经常需要查找某一个元素在线性表中的位置。
此问题的输入是待查元素x和线性表L,输出为x在L中的位置或者x不在L中的信息。
2.合并排序
3.快速排序
对本实验中的问题,设计出算法并编程实现。
实验总结及思考
3、实验过程
1.二分查找
算法:
BinSearch(aArray[0,1……n-1],key)
low<---0;
right<---n-1;
whilelow<=rightdo
m<---(low+(right-low))/2;
ifkey>aArray[mid]
l<---mid+1;
ifkeyr<---mid-1;
ifkey=aArray[mid]
returnmid;
代码:
#include
usingnamespacestd;
voidBinary(intaArray[],intkey,intlength)//二分查找
{
intmid,low,high;
mid=low=0;
high=length-1;
while(low<=high)
{
mid=low+((high-low)/2);//使用(low+high)/2会有整数溢出的问题
if(low<0||high>=length||high-low==0){
cout<<"元素不存在,查找失败"<}
if(key>aArray[mid])//key在右边
{
low=mid+1;
}
elseif(key{
high=mid-1;
}
else
{
cout<<"查找成功,元素的位置是:
"<break;
}
}
}
intmain()
{
intlength=0;
intkey=0;
cout<<"请输入数组的长度:
"<cin>>length;
int*aArray=newint[length];
cout<<"请输入数组:
"<for(inti=0;i{
cin>>aArray[i];
}
cout<<"请输入待查找的数字:
"<cin>>key;
Binary(aArray,key,length);
deleteaArray;//释放空间
return0;
}
二分查找的平均时间复杂度为O(logn)
最坏情况下的时间复杂度O(n)
运行截图:
2.合并排序
基本操作如下:
(1)分解:
将n个元素分成各含n/2个元素的子序列
(2)解决:
用合并排序法对两个子序列递归地排序
(3)合并:
合并两个已排好序的子序列得到排序结果在对子序列排序时,其长度为1时递归结束。
单个元素被视为是已排好序的。
算法:
MergeSort(A[0…n-1])
ifn>1
copyA[0…n/2-1]toB[0…n/2-1]
copyA[n/2…n-1]toC[0…n/2-1]
MergeSort(B[0…n/2-1])
MergeSort(C[0…n/2-1])
Merge(B,C,A)
Merge(B[0…p-1],C[0…q-1],A[0…P+q-1])
i<---0;j<---0;k<---0
whileiifB[i]<=C[j]
A[k]<---B[i];i<---i+1;
elseA[k]<---C[j];j<---j+1;
k<---k+1;
ifi=p
copyC[j…q-1]toA[k…p+q-1]
else
copyB[i…q-1]toA[k…p+q-1]
代码:
#include
usingnamespacestd;
voidMerge(int*a,intp,intq,intr)//把数组a[]分成L[],R[],再排序合并成a[]
{
intn1=q-p+1;
intn2=r-q;
int*L=newint[n1+1];
int*R=newint[n2+1];
inti,j,k;
for(i=0;iL[i]=a[p+i];
}
for(j=0;jR[j]=a[q+j+1];
}
L[n1]=10000000;
R[n2]=10000000;
for(i=0,j=0,k=p;k<=r;k++)
{
if(L[i]<=R[j])
{
a[k]=L[i];
i++;
}else{
a[k]=R[j];
j++;
}
}
delete[]L;
delete[]R;
}
voidMergeSort(int*a,intp,intr)//递归调用
{
if(p{
intq=(p+r)/2;
MergeSort(a,p,q);
MergeSort(a,q+1,r);
Merge(a,p,q,r);
}
}
intmain()
{
intj=0;
cout<<"请输入数组的长度:
"<cin>>j;
int*aArray=newint[j];
cout<<"请输入原始数组:
"<for(inti=0;i{
cin>>aArray[i];
}
MergeSort(aArray,0,j-1);
cout<<"排序后的数组:
"<for(inti=0;i{
cout<}
deleteaArray;//释放空间
system("pause");
return0;
}
归并排序的平均时间复杂度:
O(logn)
运行截图:
3.快速排序
实现快速排序的分治过程如下:
(1)分解:
数组A[p..r]被划分为两个(可能空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每个元素都小于等于A(q),而且,小于等于A[q+1..r]中的元素。
下标q也在这个划分过程中进行计算。
(2)解决:
通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]排序
(3)合并:
因为两个子数组是就地排序的,将它们的合并不需要操作,整个数组A[p..r]已排序。
代码:
#include
usingnamespacestd;
voidquickSort(ints[],intl,intr)
{
if(l{
inti=l,j=r;
intx=s[l];//找一个基准数
while(i{
while(i=x)//从右向左找第一个小于x的数
j--;
if(is[i++]=s[j];
while(ii++;
if(is[j--]=s[i];
}
s[i]=x;
quickSort(s,l,i-1);//递归调用
quickSort(s,i+1,r);
}
}
intmain()
{
intj=0;
cout<<"请输入数组的长度:
"<cin>>j;
int*aArray=newint[j];
cout<<"请输入原始数组:
"<for(inti=0;i{
cin>>aArray[i];
}
quickSort(aArray,0,j-1);
cout<<"排序后的数组:
"<for(inti=0;i{
cout<}
deleteaArray;
system("pause");
return0;
}
快排的平均时间复杂度O(nlogn)
最坏情况下的时间复杂度为O(n^2)
运行截图:
实验二:
回溯算法
1、实验目的
熟练掌握回溯算法
2、基本思想
回溯法在问题的解空间树中,按深度优先搜索策略,从根结点出发搜索解空间树,算法搜索至解空间树的任意一点时,先判断该结点是否满足约束,如果不满足,则跳过该节点为根的子树的搜索,逐层向其祖先节点搜索,否则,进入该子树,继续按照深度优先策略搜索。
三、实验内容:
回溯算法的几种形式
1.用回溯算法搜索子集树的一般模式
voidsearch(intm)
{
if(m>n)//递归结束条件
output();//相应的处理(输出结果)
else
{
a[m]=0;//设置状态:
0表示不要该物品
search(m+1);//递归搜索:
继续确定下一个物品
a[m]=1;//设置状态:
1表示要该物品
search(m+1);//递归搜索:
继续确定下一个物品
}
}
2.用回溯算法搜索子集树的一般模式
voidsearch(intm)
{
if(m>n)//递归结束条件
output();//相应的处理(输出结果)
else
for(i=m;i<=n;i++)
{
swap(m,i);//交换a[m]和a[i]
if()
if(canplace(m))//如果m处可放置
search(m+1);//搜索下一层
swpa(m,i);//交换a[m]和a[i](换回来)
}
}
四、回溯算法解决0-1背包问题
在0/1背包问题中,需对容量为c的背包进行装载。
从n个物品中选取装入背包的物品,每件物品i的重量为wi,价值为pi。
对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。
0代表不装进背包,1代表装进背包,对树进行深度优先搜索,判断是否为可行解,若为可行解且放进去之后最大价值大于当前最大价值则修改当前最大价值和背包余量。
(没有进行减支)
代码:
#include
voidreaddata();
voidsearch(int);
voidcheckmax();
voidprintresult();
intc=35,n=10;//c:
背包容量;n:
物品数
intw[10],v[10];//w[i]、v[i]:
第i件物品的重量和价值
inta[10],max;//a数组存放当前解各物品选取情况;max:
记录最大价值
//a[i]=0表示不选第i件物品,a[i]=1表示选第i件物品
intmain()
{
readdata();//读入数据
search(0);//递归搜索
printresult();
}
voidsearch(intm)
{
if(m>=n)
checkmax();//检查当前解是否是可行解,若是则把它的价值与max比较
else
{
a[m]=1;//不选第m件物品
search(m+1);//递归搜索下一件物品
a[m]=0;
search(m+1);
}
}
voidcheckmax()
{
inti,weight=0,value=0;
for(i=0;i{
if(a[i]==1)//如果选取了该物品
{
weight=weight+w[i];//累加重量
value=value+v[i];//累加价值
}
}
if(weight<=c)//若为可行解
if(value>max)//且价值大于max
max=value;//替换max
}
voidreaddata()
{
inti;
for(i=0;iprintf("请输入第%d个物品的重量和价值\n",i+1);
scanf("%d%d",&w[i],&v[i]);//读入第i件物品重量和价值
}
}
voidprintresult()
{
printf("背包可以装的最大价值为%d",max);
}
运行截图:
实验三:
动态规划
一、实验目的
理解动态规划的基本思想,理解动态规划算法的两个基本要素最优子结构性质和子问题的重叠性质。
熟练掌握典型的动态规划问题。
掌握动态规划思想分析问题的一般方法,对较简单的问题能正确分析,设计出动态规划算法,并能快速编程实现。
2、动态规划的基本思想
对于一个多阶段过程问题,是否可以分段实现最优决策,信赖于该问题是否有最优子结构性质,能否采用动态规划的方法,还要看该问题的子问题是否具有重叠性质。
最优子结构性质:
原问题的最优解包含了其子问题的最优解
子问题的重叠性质:
每次产生的子问题并不总是新问题,有些子问题被反复计算多次。
问题的最优子结构性质和子问题重叠性质是采用动态规划算法的两个基本要素
动态规划一般方法1.找出最优解的性质,并刻画其结构特征
2.递归地定义最优值(写出动态规划方程)
3.以自底向上的方式计算出最优值
三、用动态规划法计算矩阵连乘需要的最少乘法次数
在科学计算中经常要计算矩阵的乘积。
矩阵A和B可乘的条件是矩阵A的列数等于矩阵B的行数。
若A是一个p×q的矩阵,B是一个q×r的矩阵,则其乘积C=AB是一个p×r的矩阵。
由该公式知计算C=AB总共需要pqr次的数乘。
其标准计算公式为:
现在的问题是,给定n个矩阵{A1,A2,…,An}。
其中Ai与Ai+1是可乘的,i=1,2,…,n-1。
要求计算出这n个矩阵的连乘积A1A2…An。
递归公式:
代码:
#include
intn;//矩阵个数(0~100)
intp[101];//矩阵维数(n+1)
voidMatrix_mult()
{
intArr[101][101],temp;//(Arr[0][0]不用)Arr[i][j]存放从矩阵i到矩阵j的最小矩阵乘法数
inti,j,k;
intd;//矩阵间隔d
for(i=1;i<=n;i++)
Arr[i][i]=0;//第i个矩阵到第i个矩阵乘法数为0
for(d=1;d<=n-1;d++)//矩阵间隔r//矩阵链长度d+1
{
for(i=1;i<=n-d;i++)//i=1..~n-d
{j=i+d;//i~i+d构成长度为r+1的矩阵链
Arr[i][j]=0+Arr[i+1][j]+p[i-1]*p[i]*p[j];//截断位置为i
for(k=i+1;k{
temp=Arr[i][k]+Arr[k+1][j]+p[i-1]*p[k]*p[j];
if(tempArr[i][j]=temp;//获得从矩阵i到矩阵j的最小矩阵乘法数
}
}
}
printf("输入的%d个矩阵相乘的最少乘法数为:
",n);
printf("%d\n",Arr[1][n]);//从第1个矩阵到第n个矩阵最小乘法数
}
intmain()
{
inti;
printf("请输入矩阵的个数\n");
scanf("%d",&n);//矩阵个数(0~10)
intb[100][2];
printf("请输入n个矩阵的行数和列数\n");
for(i=0;i{
scanf("%d",&b[i][0]);//第i个矩阵的行数
scanf("%d",&b[i][1]);//第i个矩阵的列数
}
for(i=0;ip[i]=b[i][0];//存放所有矩阵维数(测例中的1,2,3...10,11)
p[n]=b[n-1][1];//最后一个矩阵的列数
Matrix_mult();
return0;
}