中南大学算法实验报告.docx
《中南大学算法实验报告.docx》由会员分享,可在线阅读,更多相关《中南大学算法实验报告.docx(36页珍藏版)》请在冰豆网上搜索。
中南大学算法实验报告
中南大学
《算法分析与设计》实验报告
姓名:
专业班级:
学号:
指导教师:
完成日期:
实验一【归并排序】
编写一个简单的程序,实现归并排序
一、实验目的:
了解并熟练掌握归并排序
二、实验内容
给定一个数组,并使其按照所要求的显示输出
三、算法思想分析
递归是简单的方法,但是其不能很好的表示出归并
非递归的方法能比较好的从底层开始显示整个归并排序的思想
四、实验过程分析
递归方法,只是先从前半部分进行拆分,组合,无法在第一部看到整个的底层的组合,所以理解上简单,但是对于排序零基础的人很难理解
五实验源代码及屏幕
#include"stdafx.h"
#include
#include
usingnamespacestd;
voidmerge(intarray[],intleft,intlength)//合并
{
int*temp=newint[length];
intk=0;
intleft1=left;
intleft2=left+length/2;
intend1=left+length/2-1;
intend2=left+length-1;
while((left1<=end1)&&(left2<=end2))//是否到末尾
{
if(array[left1]{
temp[k]=array[left1];
left1++;
}
else
{
temp[k]=array[left2];
left2++;
}
k++;
}
while(left1<=end1)//若前半部分到末尾
{
temp[k++]=array[left1++];
}
while(left2<=end2)//若后半部分到末尾
{
temp[k++]=array[left2++];
}
for(inti=0;i{
array[left+i]=temp[i];
}
delete[](temp);
}
voidmerge_sort(intarray[],intsize)/*归并排序*/
{
for(inti=2;i<=pow(2,ceil(log(size)/log
(2)));i*=2)
{
for(intj=0;j{
merge(array,j,i);
}
cout<<"第"<(2)<<"趟:
[";
for(intk=0;k{
if((k+1)%i==0&&(k+1)!
=size)
cout<elseif(k==(size-1))
cout<else
cout<}
cout<<"]"<}
intmain()
{
intdata[]={8,4,5,6,2,1,7,3};
cout<<"归并排序初始片段";
for(inti=0;i<8;i++)
{
cout<}
cout<merge_sort(data,8);
return0;
}
实验二快速排序
一、实验目的
熟练掌握快速排序及快速排序每步
二、实验内容
编写一段程序,实现快速排序
三、算法思想分析
设置一个哨兵点,然后将比哨兵小的放置在左边,把比哨兵点大的放在右边
四、实验过程分析
第一个点搜索,遇见比他小的,交换位置,新的哨兵点形成,依次
五、
intpartition(intarray[],intleft,intright)//分解
{
ints;
s=array[left];
while(left{
while(array[right]>s)
right--;
while(array[left]
left++;
swap(array[left],array[right]);
}
cout<<"快速排序每次交换";
for(inti=0;i<8;i++)
{
cout<}
cout<array[left]=s;
returnleft;
}
voidquicksort(intarray[],intleft,intright)//快速排序
{
intq;
if(left{
q=partition(array,left,right);//分解
quicksort(array,left,q-1);//排序
quicksort(array,q+1,right);
}
}
实验三:
循环赛日程表
实验目的:
更加清楚详细的了解分治算法以及其在显示生活中的应用
实验内容:
(1)编写程序实现循环赛日程表。
设有n=2k个运动员要进行网球循环赛。
现要设计一个满足以下要求的比赛日程表:
(1)每个选手必须与其它n-1个选手各赛一次
(2)每个选手一天只能赛一场(3)循环赛进行n-1天
三,实验算法思想
主要是使用分治算法,大数据方面很难排序,比如八个队VS八个队,16个队VS16个队,都是很难进行所谓的排列日程表
若是我们从2个队VS2个队开始,就比较好用了吧,所以,分治算法就是如此
四,实验过程分析
将日程表显示出来,就必须要输出这个界面,我们暂且使用2维数组来做出这个表。
五,源代码以及截图
#include
#include
#include
usingnamespacestd;
#defineMAXN64
#defineMAX32
inta[MAX][MAX];//日程表数组
voidCopy(inttox,inttoy,intfromx,intfromy,intn)
{inti,j;
for(i=0;ifor(j=0;ja[tox+i][toy+j]=a[fromx+i][fromy+j];
}
voidTable(intk,inta[][MAX])
{inti,n=1*pow(2,k);//1<intr;
for(i=0;ia[0][i]=i+1;
for(r=1;r{for(i=0;i{Copy(r,i+r,0,i,r);
Copy(r,i,0,i+r,r);
}
}
}
voidOut(inta[][MAX],intn)
{inti,j;
for(i=0;i{for(j=0;jcout<cout<<"\n";
}
printf("\n");
}
voidmain()
{inti;
for(i=0;i<5;i++)
{intlen=1*pow(2,i);//1<
Table(i,a);Out(a,len);
}
}
实验2贪心算法实验
1、实验目的
(1)了解贪心算法思想
(2)掌握贪心法典型问题,如背包问题、作业调度问题等。
2、实验内容
(1)编写一个简单的程序,实现单源最短路径问题。
(2)编写一段程序,实现找零。
【问题描述】当前有面值分别为2角5分,1角,5分,1分的硬币,请给出找n分钱的最佳方案(要求找出的硬币数目最少)。
(3)编写程序实现多机调度问题
【问题描述】要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。
约定,每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。
作业不能拆分成更小的子作业。
(4)
设N=8,[w1,…w8]=[100,200,50,90,150,50,20,80],C=400。
编程求t[1..8].
3、实验要求
(1)写出源程序,
(2)并编译运行
(3)详细记录程序调试及运行结果
1.
单元最短路径问题:
#include
#include
usingnamespacestd;
#defineVEX5//定义结点的个数
#definemaxpoint100
doublegraph[][maxpoint]={
{0,10,-1,30,100},
{-1,0,50,-1,-1},
{-1,-1,0,-1,10},
{-1,-1,20,0,60},
{-1,-1,-1,-1,0}
};//邻接矩阵
voidmain()
{intR[maxpoint]={0},B[maxpoint];
intD[VEX],P[VEX];//定义数组D用来存放结点特殊距离,P数组存放父亲结点
//初始时,红点集中仅有源结点0
R[0]=1;B[0]=0;
for(inti=1;iB[i]=1;
//对数组D、P进行初始化
for(i=0;i{D[i]=graph[0][i];
if(D[i]!
=-1)P[i]=0;
elseP[i]=-1;
}
//输出邻接矩阵
for(i=0;i{for(intj=0;jcout<cout<}
//输出D、P表头
cout<<"";
for(i=0;icout<<"D["<
cout<<"";
for(i=0;icout<<"P["<
cout<for(intk=1;k{for(intmin=0;B[min]==0;)min++;//求蓝点集结点最小下标元素
for(intj=min;jif(D[j]!
=-1&&D[j]cout<<"min="<//将具有最短特殊路长度的结点min添加到红点集中
R[min]=1;B[min]=0;
//对数组D作必要的修改
for(j=1;jif(graph[min][j]!
=-1&&min!
=j)//结点min到j间有路
if(D[j]>D[min]+graph[min][j]||D[j]==-1)
{D[j]=D[min]+graph[min][j];//每次迭代求最小值,最后一次即为到源点的最短路径
P[j]=min;
}
//输出最短路径
for(i=0;icout<cout<<"";
for(i=0;icout<
cout<}
}
2
零钱问题
#include
usingnamespacestd;
voidchangemoney(intmoney)
{intcount[4]={0,0,0,0};
intchange[4]={25,10,5,1};
inti=0;
while(i<4)
{
while(money>=change[i])
{
money=money-change[i];
count[i]++;
}
i++;
}
cout<<"找的零钱为"<cout<cout<cout<cout<}
intmain()
{
intn;
cout<<"请输入你要找的零钱数量"<cin>>n;
changemoney(n);
return0;
}
3
多机调度
//ManyToWork.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include
usingnamespacestd;
#defineN10//作业数
#defineM3//机器数
voidsort(intt[],intn);
intset_work1(intt[],intn);
intmax(intt[],intnum);
intmin(intt[],intm);
intset_work2(intt[],intn);
//S数组存储每台机器当前已分配任务总耗时
staticinttime[N]={2,8,18,32,50,72,98,128,182,200},s[M]={0,0,0};
voidmain()
{sort(time,N);
cout<<"最短时间为";
if(M>=N)//作业数小于机器数
cout<else
cout<}
voidsort(intt[],intn)
{for(intk=0;k{intj=k;
for(inti=k;iif(t[i]>t[j])j=i;
{inttemp=t[j];t[j]=t[k];t[k]=temp;}
}
}
intmax(intt[],intnum)//max函数求解处理时间总和最长
{intmax=t[0];
for(inti=1;iif(maxreturnmax;
}
intmin(intt[],intm)
{intmin=0;//min记录目前处理作业时间和最小的机器号
for(inti=1;iif(s[min]>s[i])min=i;
returnmin;
}
intset_work1(intt[],intn)
{intm=0;
for(inti=0;is[m++]+=t[i];
returnmax(s,N);
}
intset_work2(intt[],intn)
{for(inti=0;is[min(s,M)]+=t[i];
returnmax(s,M);
}
4
最优装载问题
#include"iostream"
#include"math.h"
usingnamespacestd;
voidchange(intarray[],intt[])
{inti;
inttemp[8];
intcount=0;
while(count<8)
{inttemp1=0;
for(i=0;i<8;i++)
{
if(array[temp1]<0)
temp1++;
}
for(i=0;i<8;i++)
{
if(array[i]<=array[temp1]&&array[i]>0)
temp1=i;
}
temp[temp1]=array[temp1];
array[temp1]=-1;
t[count]=temp1+1;
count++;
}
for(i=0;i<8;i++)
{
array[i]=temp[i];
}
}
intmain()
{inti;
intdata[8];
for(i=0;i<8;i++)
{
data[i]=10*(rand()%20+1);
}
intt[8]={0,0,0,0,0,0,0,0};
change(data,t);
cout<<"原各货箱的载重如下:
"<for(i=0;i<8;i++)
{
cout<}
cout<cout<<"货箱重量排序为:
"<for(i=0;i<8;i++)
{
cout<}
cout<return0;
}
实验3动态规划算法实验
1、实验目的
(1)掌握动态规划方法贪心算法思想
(2)掌握最优子结构原理
(3)了解动态规划一般问题
2、实验内容
(1)编写一个简单的程序,解决0-1背包问题。
设N=5,C=10,w={2,2,6,5,4},v={6,3,5,4,6}
(2)合唱队形安排。
【问题描述】N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:
设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,则他们的身高满足T1<...Ti+1>…>TK(1<=i<=K)。
已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
3、实验要求
(1)写出源程序,并编译运行
详细记录程序调试及运行结果
#include
#include
usingnamespacestd;
intm[5][11];
intyesno[5];
#defineN5
#definec10
intmin(intx,inty)
{
if(x<=y)returnx;
elsereturny;
}
intmax(intx,inty)
{
if(x>=y)returnx;
elsereturny;
}
voidpackage(intv[],intw[])
{
intjMax=min(w[1],c);
for(intj=0;j<=jMax;j++)
m[1][j]=0;
for(intj=w[0];j<=c;j++)
m[1][j]=v[0];
for(inti=2;i<=N;i++)
{
intjMax=min(w[i-1],c);
for(intj=1;jm[i][j]=m[i-1][j];
for(intj=jMax;j<=c;j++)
m[i][j]=max(m[i-1][j],m[i-1][j-w[i-1]]+v[i-1]);
}
}
voidmain()
{
intw[6]={2,2,6,5,4},v[6]={6,3,5,4,6};
package(v,w);
for(inti=1;i<=N;i++)
{
for(intj=0;j<=c;j++)
cout<cout<}
}
2
#include
#include
usingnamespacestd;
voidmain()
{
intn;//队列个数
inta[100];//原始队列
intb[100];//上升序列
intc[100];//下降序列
intpre[100];
intafter[100];
intman[100];
inti,j,max,index;
intbnumber;
intcnumber;
cout<<"请输入你的队列总人数"<cin>>n;
cout<<"请输入队列各队员的身高"<for(i=1;i<=n;i++)
{
cin>>a[i];
}
memset(b,0,sizeof(a));
memset(c,0,sizeof(c));
memset(pre,0,sizeof(pre));
memset(after,0,sizeof(after));//初始化为全部为出列
//左边上升序列b[i]指的是第I个人左边可以构成多长的序列
b[1]=1;
for(i=2;i<=n;i++)
{
max=0;
for(j=i-1;j>=1;j--)
{
if(a[j]max)
{
max=b[j];
pre[i]=j;
}
}
b[i]=max+1;
}
//右边下降序列,
c[n]=1;
for(i=n-1;i>0;i--)
{
max=0;
for(j=i+1;j<=n;j++)
{
if(