算法设计与分析实验四.docx
- 文档编号:3658625
- 上传时间:2022-11-24
- 格式:DOCX
- 页数:17
- 大小:84.10KB
算法设计与分析实验四.docx
《算法设计与分析实验四.docx》由会员分享,可在线阅读,更多相关《算法设计与分析实验四.docx(17页珍藏版)》请在冰豆网上搜索。
算法设计与分析实验四
实验四:
贪心法
一、实验目的
1、掌握贪心算法的基本设计思想与原则
2、运用贪心法求解经典问题(验证性实验)
二、实验原理
1、优化问题
有n个输入,而它的解就由这n个输入满足某些事先给定的约束条件的某个子集组成,而把满足约束条件的子集称为该问题的可行解。
可行解一般来说是不唯一的。
那些使目标函数取极值(极大或极小)的可行解,称为最优解。
2、贪心法求优化问题
算法思想:
在贪心算法中采用逐步构造最优解的方法。
在每个阶段,都作出一个看上去最优的决策(在一定的标准下)。
决策一旦作出,就不可再更改。
作出贪心决策的依据称为贪心准则(greedycriterion)。
3、一般方法
1)根据题意,选取一种量度标准。
2)按这种量度标准对这n个输入排序
3)依次选择输入量加入部分解中。
如果当前这个输入量的加入,不满足约束条件,则不把此输入加到这部分解中。
procedureGREEDY(A,n)/*贪心法一般控制流程*/
//A(1:
n)包含n个输入//
solutions←φ//将解向量solution初始化为空/
fori←1tondo
x←SELECT(A)
ifFEASIBLE(solution,x)
thensolutions←UNION(solution,x)
endif
repeat
return(solution)
endGREEDY
三、实验要求
1、用C++/C完成算法设计和程序设计并上机调试通过。
2、撰写实验报告,提供实验结果和数据。
3、分析算法,要求给出具体的算法分析结果,包括时间复杂度和空间复杂度,并简要给出算法设计小结和心得。
四、实验内容
1、哈夫曼编码
设需要编码的字符集为{d1,d2,…,dn},它们出现的频率为{w1,w2,…,wn},应用哈夫曼树构造最短的不等长编码方案。
设需要编码的字符集为{d1,d2,…,dn},它们出现的频率为{w1,w2,…,wn},以d1,d2,…,dn作为叶子结点,w1,w2,…,wn作为叶子结点的权值,构造一棵哈夫曼编码树,规定哈夫曼编码树的左分支代表0,右分支代表1,则从根结点到每个叶子结点所经过的路径组成的0和1的序列便为该叶子结点对应字符的编码即为哈夫曼编码。
考虑到哈夫曼树中共有2n-1个结点,并且进行n-1次合并操作,为了便于选取根结点权值最小的二叉树以及合并操作,设置一个数组huffTree[2n-1]保存哈夫曼树中各结点的信息,数组元素的结点结构如下图所示。
将数组元素的结点类型定义为:
structelement
{
doubleweight;//字符出现的概率为实数
intlchild,rchild,parent;
};
建立哈夫曼树的算法如下:
Select函数用来在数组huffTree中选取两个权值最小的根结点,请读者自行完成。
根据已建立的哈夫曼树,规定哈夫曼树的左分支代表0,右分支代表1,则哈夫曼编码即是从根结点到每个叶子结点所经过的路径组成的0和1的序列。
算法如下:
2、背包问题
贪心算法:
procedureKNAPSACK(P,W,M,X,n)
//P(1:
n)和W(1;n)分别含有按
P(i)/W(i)≥P(i+1)/W(i+1)排序的n件物品的效益值
和重量。
M是背包的容量大小,而x(1:
n)是解向量
realP(1:
n),W(1:
n),X(1:
n),M,cu;
integeri,n;
X←0//将解向量初始化为零
cu←M//cu是背包剩余容量
fori←1tondo
ifW(i)>cuthenexitendif
X(i)←1
cu←cu-W(i)
repeat
ifi≤nthenX(i)←cu/W(i)
endif
endGREEDY-KNAPSACK
procedureprim(G,)
status←“unseen”//T为空
status[1]←“treenode”//将1放入T
foreachedge(1,w)do
status[w]←“fringe”//找到T的邻接点
dad[w]←1;//w通过1与T建立联系
dist[w]←weight(1,w)//w到T的距离
repeat
whilestatus[t]≠“treenode”do
pickafringeuwithmindist[w]//选取到T最近的节点
status[u]←“treenode”
foreachedge(u,w)do
修改w和T的关系
repeat
repeat
3、最小生成树的prim算法
PrimMST(G,T,r){
//求图G的以r为根的MST,结果放在T=(U,TE)中
InitCandidateSet(…);//初始化:
设置初始的轻边候选集,并置T=({r},¢)
for(k=0;k (u,v)=SelectLiShtEdge(…);//选取轻边(u,v); T←T∪{(u,v)};//扩充T,即(u,v)涂红加入TE,蓝点v并人红点集U ModifyCandidateSet(…);//根据新红点v调整候选轻边集 } } 4、最短路径问题 最短路径问题是图论研究中的一个经典算法问题,旨在寻找图中两结点之间的最短路径。 给定带权有向图G=(V,E),其中每条边的权是非负实数。 另外,还给定V中的一个顶点,称为源。 现在要计算从源到所有其它各顶点的最短路长度。 这里路的长度是指路上各边权之和。 这个问题通常称为单源最短路径问题。 Dijkstra算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。 主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。 Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。 创建两个表,OPEN,CLOSE。 OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。 1)访问路网中距离起始点最近且没有被检查过的点,把这个点放入OPEN组中等待检查。 2)从OPEN表中找出距起始点最近的点,找出这个点的所有子节点,把这个点放到CLOSE表中。 3)遍历考察这个点的子节点。 求出这些子节点距起始点的距离值,放子节点到OPEN表中。 4)重复第2和第3步,直到OPEN表为空,或找到目标点。 算法描述: 1)置集合S={2,3,...n},数组d (1)=0,d(i)=W1->i(1,i之间存在边)or+无穷大(1.i之间不存在边) 2)在S中,令d(j)=min{d(i),i属于S},令S=S-{j},若S为空集则算法结束,否则转3) 3)对全部i属于S,如果存在边j->i,那么置d(i)=min{d(i),d(j)+Wj->i},转2) Dijkstra算法思想为: 设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径,就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。 在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。 此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。 算法具体步骤: (1)初始时,S只包含源点,即S=,v的距离为0。 U包含除v外的其他顶点,U中顶点u距离为边上的权(若v与u有边)或)(若u不是v的出边邻接点)。 (2)从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。 (3)以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u(uU)的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。 (4)重复步骤 (2)和(3)直到所有顶点都包含在S中。 5、多机调度问题 要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。 约定,每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。 作业不能拆分成更小的子作业。 步骤: 1)把作业按加工所用的时间从大到小排序 2)如果作业数目比机器的数目少或相等,则直接把作业分配下去 3)如果作业数目比机器的数目多,则每台机器上先分配一个作业,如下的作业分配时,是选那个表头上s最小的链表加入新作业。 五、参考程序 2、背包问题贪心算法 #include structgoodinfo { floatp;//物品效益 floatw;//物品重量 floatX;//物品该放的数量 intflag;//物品编号 };//物品信息结构体 voidInsertionsort(goodinfogoods[],intn) { intj,i; for(j=2;j<=n;j++) { goods[0]=goods[j]; i=j-1; while(goods[0].p>goods[i].p) { goods[i+1]=goods[i]; i--; } goods[i+1]=goods[0]; } }//按物品效益,重量比值做升序排列 voidbag(goodinfogoods[],floatM,intn) { floatcu; inti,j; for(i=1;i<=n;i++) goods[i].X=0; cu=M;//背包剩余容量 for(i=1;i { if(goods[i].w>cu)//当该物品重量大与剩余容量跳出 break; goods[i].X=1; cu=cu-goods[i].w;//确定背包新的剩余容量 } if(i<=n) goods[i].X=cu/goods[i].w;//该物品所要放的量 for(j=2;j<=n;j++) { goods[0]=goods[j]; i=j-1; while(goods[0].flag { goods[i+1]=goods[i]; i--; } goods[i+1]=goods[0]; } cout<<"最优解为: "< for(i=1;i<=n;i++) { cout<<"第"< "; cout< } } voidmain() { cout<<"|--------运用贪心法解背包问题---------|"< cout<<"|-------------------------------------|"< intj; intn; floatM; goodinfo*goods;//定义一个指针 while(j) { cout<<"请输入物品的总数量: "; cin>>n; goods=newstructgoodinfo[n+1];// cout<<"请输入背包的最大容量: "; cin>>M; cout< inti; for(i=1;i<=n;i++) {goods[i].flag=i; cout<<"请输入第"< "; cin>>goods[i].w; cout<<"请输入第"< "; cin>>goods[i].p; goods[i].p=goods[i].p/goods[i].w;//得出物品的效益,重量比 cout< } Insertionsort(goods,n); bag(goods,M,n); cout<<"press<1>torunagian"< cout<<"press<0>toexit"< cin>>j; } } 3、最小生成树的prim算法 #include #include #include #defineINFINITYINT_MAX #defineMAX_VERTEX_NUM20 typedefintVRType; typedefintInfoType; typedefcharVerTexType; typedefstructArcCell { VRTypeadj; InfoType*info; }ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedefstruct { VerTexTypevexs[MAX_VERTEX_NUM]; AdjMatrixarcs; intvexnum,arcnum; }MGraph; typedefstruct { VerTexTypeadjvex; VRTypelowcost; }closedge[MAX_VERTEX_NUM]; voidCreateGraph(MGraph&G); voidMiniSpanTree_PRIM(MGraphG,VerTexTypeu); intLocateVex(MGraphG,VerTexTypeu); intminimum(closedgeclose); voidmain(void) { inti,j; MGraphG; CreateGraph(G); for(i=0;i { for(j=0;j { cout< cout<<""; } cout< } MiniSpanTree_PRIM(G,'a'); } voidCreateGraph(MGraph&G) { intweigh; inti,j=0,k=0; charhand,tide; cout<<"inputthenumberforvexnumandarcnum: "; cin>>G.vexnum>>G.arcnum; for(i=0;i { for(j=0;j G.arcs[i][j].adj=88; } cout< cout<<"input"< "; for(i=0;i cin>>G.vexs[i]; cout< cout<<"input"< "< j=0; k=0; for(i=0;i { cout< "; cin>>hand; cin>>tide; cin>>weigh; while(hand! =G.vexs[j]) j++; while(tide! =G.vexs[k]) k++; G.arcs[j][k].adj=weigh; G.arcs[k][j].adj=weigh; j=0; k=0; cout< } } voidMiniSpanTree_PRIM(MGraphG,VerTexTypeu) { inti,j,k=0; closedgeclose; k=LocateVex(G,u); for(j=0;j { if(j! =k) { close[j].adjvex=G.vexs[k]; close[j].lowcost=G.arcs[k][j].adj; } } close[j].lowcost=88; close[j].adjvex='\0'; close[k].lowcost=0; close[k].adjvex=u; for(i=1;i { k=minimum(close); cout< cout<<"---->"; cout< cout< close[k].lowcost=0; for(j=0;j { if(G.arcs[k][j].adj { close[j].adjvex=G.vexs[k]; close[j].lowcost=G.arcs[k][j].adj; } } } } intLocateVex(MGraphG,VerTexTypeu) { intk=0; while(G.vexs[k++]==u) returnk-1; return0; } intminimum(closedgeclose) { intj1=0,client=88,j2; while(close[j1].adjvex! ='\0') { if(client>close[j1].lowcost&&close[j1].lowcost! =0) { client=close[j1].lowcost; j2=j1; } j1++; } returnj2; } 4、最短路径问题 #include #include usingnamespacestd; constintMaxNum=1000000;//边权最大值 intn;//节点数目 intdist[501];//到节点1的最短路径值 boolstate[501];//节点被搜索过状态指示 intdata[501][501];//邻接矩阵 //查找权值最小的节点 intfindmin() { intminnode=0,min=MaxNum; for(inti=1;i<=n;i++) if((dist[i] state[i])) { min=dist[i]; minnode=i; } returnminnode; } intmain() { ifstreamin("dijkstra.in"); ofstreamout("dijkstra.out"); memset(state,0,sizeof(state)); in>>n; for(intp=1;p<=n;p++) for(intq=1;q<=n;q++) { in>>data[p][q]; if(data[p][q]==0)data[p][q]=MaxNum; } //初始化 for(inti=1;i<=n;i++) dist[i]=data[1][i]; state[1]=true; intdone=1; while(done { intnode=findmin(); if(node! =0) { done++;//找到的点的数目加1 state[node]=true;//标记已经找到了从节点1到节点node的最短路径 for(inti=1;i<=n;i++)//更新还没有找到的点的路径值 if((dist[i]>dist[node]+data[node][i])&&(! state[i])) dist[i]=dist[node]+data[node][i]; } elsebreak; } for(intk=1;k<=n;k++) { if(dist[k]==MaxNum) out<<-1; else out< if(k==n) out< else out<<""; } in.close(); out.close(); return0; } 5、多机调度问题 typedefstructJob { intID;//作业号 inttime;//作业所花费的时间 }Job; typedefstructJobNode//作业链表的节点 { intID; inttime; JobNode*next; }JobNode,*pJobNode; typedefstructHeader //链表的表头 { ints; pJobNodenext; }Header,pHeader; intSelectMin(Header*M,intm) { intk=0; for(inti=1;i { if(M[i].s } returnk; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 设计 分析 实验