中南大学算法实验报告Word文件下载.docx
- 文档编号:20442086
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:19
- 大小:271.31KB
中南大学算法实验报告Word文件下载.docx
《中南大学算法实验报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《中南大学算法实验报告Word文件下载.docx(19页珍藏版)》请在冰豆网上搜索。
voidPrintArray(int*arr)
for(inti=1;
i<
=num;
++i)
cout<
<
arr[i]<
"
;
endl;
}
intPartition1(int*arr,intp,intr)
intx=arr[r];
inti=p-1;
intj;
for(j=p;
j<
=r-1;
j++)
{
if(arr[j]<
=x)
{i=i+1;
swap(arr[i],arr[j]);
}
swap(arr[i+1],arr[r]);
returni+1;
}//对子数组A[p..r]进行就地重排
voidQuickSort(int*arr,intp,intr)
if(p<
r)
intq=Partition1(arr,p,r);
QuickSort(arr,p,q-1);
QuickSort(arr,q+1,r);
}//该过程实现快速排序
intmain()
intarr[100];
请输入元素个数:
\n"
cin>
>
num;
请输入元素大小:
arr[i];
QuickSort(arr,1,num);
最后结果:
"
PrintArray(arr);
return0;
运行结果如下图所示:
实验收获与体会:
通过证明可以得到该算法在最坏情况下的时间复杂性为T(n)=O(n^2),平均情况下的时间复杂性是O(nlogn),通过该实验对分治法基本思想有了了解。
2.归并排序:
基本操作如下:
将n个元素分成各含n/2个元素的子序列
用合并排序法对两个子序列递归地排序
合并两个已排好序的子序列得到排序结果
在对子序列排序时,其长度为1时递归结束。
单个元素被视为是已排好序的。
#include<
iostream.h>
string.h>
template<
classT>
voidMerge(Tc[],Td[],intl,intm,intr)
{//把c[l:
m]和c[m:
r]归并到d[l:
r]
inti,j,k;
i=l;
//第一段游标
j=m+1;
//第二段游标
k=l;
//结束游标
while((i<
=m)&
&
(j<
=r))
if(c[i]<
=c[j])
d[k++]=c[i++];
elsed[k++]=c[j++];
if(i>
m)for(intq=j;
q<
=r;
q++)
d[k++]=c[q];
elsefor(intq=i;
=m;
voidMergePass(Tx[],Ty[],ints,intn){
//归并大小为s的相邻的段
inti=0;
while(i<
=n-2*s){
//归并两个大小为s的相邻段
Merge(x,y,i,i+s-1,n-1);
i=i+2*s;
//剩下不足两个元素
if(i+s<
n)Merge(x,y,i,i+s-1,n-1);
elsefor(intj=i;
=n-1;
//把最后一段复制到y
y[j]=x[j];
voidMergeSort(Ta[],intn)
{T*b=newT[n];
ints=1;
while(s<
n){
MergePass(a,b,s,n);
s+=s;
MergePass(b,a,s,n);
intn,i,j=0;
double*Input;
cout<
请输入您要排序的元素个数"
endl;
cin>
n;
Input=newdouble[100000];
//定义排序数组
cout<
请输入您要排序的元素:
for(i=0;
i<
i++)
cin>
*(Input+i);
MergeSort(Input,n);
//调用排序函数
排序后的数组元素为:
Input[i]<
j++;
if(j%10==0)
cout<
delete[]Input;
//释放内存;
运行结果如下图所示:
通过归并排序的实验对分治法在排序中的应用有了更深刻的了解,与快速排序对比,归并排序相对较“稳定”些。
3.最大最小值问题:
每次将问题分成大致相等的两部分,分别在这两部分中找出最大值与最小值,再将这两个子问题的解组合成原问题的解,就可得到该问题的分治算法。
算法描述:
procedureMAXMIN(i,j,fmax,fmin)
globaln,A[1:
n]
case
{i=j:
fmax←fmin←A[i]/*只有一个元素*/
i=j-1:
ifA[i]<
A[j]then/*两个元素*/
fmax←A[j];
fmin←A[i]
elsefmax←A[i];
fmin←A[j]
else:
mid←(i+j)/2/*分成两部分*/
MAXMIN(i,mid,max1,min1)
MAXMIN(mid+1,j,max2,min2)
fmax←max(max1,max2)
fmin←min(min1,min2)
}
如果MAX1和MIN1是I1中的最大和最小元素,MAX2和MIN2是I2中的最大和最小元素,MAX1和MAX2中的大者就是I中的最大元素MAX,MIN1和MIN2中的小者是I中的最小元素MIN。
如果I只包含一个元素,则不需要作任何分割直接就可得到其解。
#include"
stdio.h"
#defineN100
voidmaxmin2(intA[],inti,intj,int*max,int*min)
{
intmid,max1,max2,min1,min2;
if(j==i)
{*max=*min=A[i]=A[j];
return;
if(j-1==i)
if(A[i]>
A[j])
{
*max=A[i];
*min=A[j];
}
else
{
*max=A[j];
*min=A[i];
mid=(i+j)/2;
maxmin2(A,mid+1,j,&
max2,&
min2);
maxmin2(A,i,mid,&
max1,&
min1);
if(max1>
max2)
*max=max1;
else
*max=max2;
if(min1>
min2)
*min=min2;
*min=min1;
main()
inti,n;
intA[N];
intmax,min;
printf("
请输入要比较的数据的个数:
);
scanf("
%d"
&
n);
{
printf("
请输入第%d个数"
i+1);
A[i]);
maxmin2(A,0,n-1,&
max,&
min);
最大值为:
%d最小值为:
max,min);
通过该实验对分治法掌握的更加透彻,明白了分治法发挥的作用。
动态规划实验
对于一个多阶段过程问题,是否可以分段实现最优决策,信赖于该问题是否有最优子结构性质,能否采用动态规划的方法,还要看该问题的子问题是否具有重叠性质。
最优子结构性质:
原问题的最优解包含了其子问题的最优解
子问题的重叠性质:
每次产生的子问题并不总是新问题,有些子问题被反复计算多次。
问题的最优子结构性质和子问题重叠性质是采用动态规划算法的两个基本要素
动态规划一般方法
1.找出最优解的性质,并刻画其结构特征
2.递归地定义最优值(写出动态规划方程)
3.以自底向上的方式计算出最优值
多段图
多段图算法:
ProcedureFGRAPH(E,k,n,P)
//输入是按段的顺序给结点编号的,有n个结点的k段图。
E是边集,c(i,j)是边<
i,j>
的成本。
P(1:
k)是最小成本路径。
//
realCOST(n),integer(n-1),P(k),r,j,k,n
COST(n)<
-0
forj<
-n-1to1by-1do//计算COST(j)//
设r是一个这样的结点,(j,r)
E且使c(j,r)+COST(r)取最小值
COST(j)<
-c(j,r)+COST(r);
D(j)<
-r;
Repeat//向前对j-1进行决策//
P
(1)<
-1;
P(k)<
-n;
-2tok-1do//找路径上的第j个节点//
P(j)<
-D(P(j-1));
repeat;
endFGRAPH
#defineMAX100
#definen12//图的总顶点数
#definek5//图的段数
intc[n][n];
voidinit(intcost[])//初始化图
inti,j;
13;
for(j=0;
c[i][j]=MAX;
//初始化每条边长度为MAX
c[1][2]=9;
c[1][3]=7;
c[1][4]=3;
c[1][5]=2;
c[2][6]=4;
c[2][7]=2;
c[2][8]=1;
c[3][6]=2;
c[3][7]=7;
c[4][8]=11;
c[5][7]=11;
c[5][8]=8;
c[6][9]=6;
c[6][10]=5;
c[7][9]=4;
c[7][10]=3;
c[8][10]=5;
c[8][11]=6;
c[9][12]=4;
c[10][12]=2;
c[11][12]=5;
//给每条边赋值
voidfront(intcost[],intpath[],intd[])//向前递推算法求多段图的最短路径
intr,j,temp,min;
for(j=0;
=n;
cost[j]=0;
for(j=n-1;
j>
=1;
j--)
temp=0;
min=c[j][temp]+cost[temp];
//初始化当前路径长度的最小值
for(r=0;
r<
r++)
if(c[j][r]!
=MAX)
{
if((c[j][r]+cost[r])<
min)//找到最小的r,使c[j][r]+cost[r]取最小值
{
min=c[j][r]+cost[r];
temp=r;
}
}
}
cost[j]=c[j][temp]+cost[temp];
d[j]=temp;
}//向前对j-1进行决策
path[1]=1;
//第一段所取节点
path[k]=n;
//最后一段所取节点
for(j=2;
k;
path[j]=d[path[j-1]];
//找到路径上第j个节点
voidback(intbcost[],intpath1[],intd[])//使用向后递推算法求多段图的最短路径
bcost[j]=0;
temp=12;
min=c[temp][j]+bcost[temp];
//初始化当前路径长度最小值
if(c[r][j]!
if((c[r][j]+bcost[r])<
min)//找到最小的r使c[r][j]+bcost[r]最小
min=c[r][j]+bcost[r];
bcost[j]=c[temp][j]+bcost[temp];
path1[1]=1;
path1[k]=n;
for(inti=4;
i>
=2;
i--)
path1[i]=d[path1[i+1]];
}//找出各段的节点
intcur=-1;
intcost[13],d[12],bcost[13];
intpath[k];
intpath1[k];
\t\t\t\t多段图问题"
\n\n"
init(cost);
front(cost,path,d);
向前递推算法求得的最短路径:
=5;
if(i==5)
path[i]<
->
endl<
最短路径:
cost[1]<
向后递推算法求得的最短路径:
back(bcost,path1,d);
for(j=1;
if(j==5)
path[j]<
path1[j]<
bcost[12]<
通过多段图实验对动态规划的思想有了更深理解,动态规划与分治法类似,基本思想也是将待求解问题分成若干个子问题,但是分解得到的子问题往往不是互相独立的。
回溯法实验
回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。
算法搜索至解空间树的任意一点时,先判断该结点是否满足约束。
如果不满足,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;
否则,进入该子树,继续按深度优先策略搜索。
N皇后:
基本思想:
(1)针对所给问题,定义问题的解空间,使N个皇后不在同行同列,对角线上;
(2)确定易于搜索的解空间结构;
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
math.h"
classQUEEN
public:
friendintnQueen(int);
private:
boolPlace(intk);
voidBacktrack(intt);
intn,*x;
longsum;
};
intnQueen(intn)
QUEENx;
x.n=n;
x.sum=0;
int*p=newint[n+1];
for(inti=0;
p[i]=0;
x.x=p;
x.Backtrack
(1);
delete[]p;
returnx.sum;
boolQUEEN:
:
Place(intk)
for(intj=1;
if((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k]))
returnfalse;
returntrue;
voidQUEEN:
Backtrack(intt)
if(t>
n){sum++;
n皇后问题的第"
sum<
个"
可行解的坐标为:
for(t=1;
t<
t++)
("
"
x[t]<
)"
********"
for(inti=1;
x[t]=i;
if(Place(t))
Backtrack(t+1);
//递归求解
intmain()
{intn;
cout<
***************N皇后问题***************"
请输入皇后的个数n:
cin>
nQueen(n)<
***************N皇后问题结束*************"
通过该实验对回溯法的思想有了较深的了解,通过亲手实践,加深了记忆与理解,该实验的算法也可以用在类似有关回溯法问题上。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 中南 大学 算法 实验 报告