ImageVerifierCode 换一换
格式:DOCX , 页数:19 ,大小:55.68KB ,
资源ID:26553002      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/26553002.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(实验5物联1301班刘悦08080112.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

实验5物联1301班刘悦08080112.docx

1、实验5物联1301班刘悦08080112算法分析与设计实验报告第 5 次实验姓名刘悦学号201308080112班级物联1301班时间12.12上午地点工训楼C栋309 实验名称贪心法求最短路径实验目的 通过上机实验,掌握贪心算法的思想,利用Dijkstra 算法求解最短路径并实现。实验原理使用Dijkstra算法。即每次从未遍历顶点中,选择到源结点距离最小的点。然后更新这个点的邻接点到源结点的距离值。重复这个步骤,直至所有的结点均被遍历。实验步骤1 用邻接矩阵表示有向图,并进行初始化,同时选择源结点与目的结点。2 选取候选集中距离最短的顶点,把其加入终点集合。3 考虑此顶点的邻接顶点,若经过

2、此顶点后,其邻接顶点的到达源结点的距离比原来的距离短,则修改其距离。4 重复上面的步骤,直至所有的顶点均被遍历。关键代码/*= 定义图类来存储图的信息。 =*/class Graph private: int numVertex;/图的顶点数 int *matrix; /图的边权值 int *mark; /记录顶点是否被访问 public: /构造函数 Graph(int numVert) Init(numVert);/调用初始化函数 /析构函数 /删除动态分配的内存 Graph() delete mark; for(int i=0;i=numVertex;i+) delete matrixi

3、; delete matrix; /初始化函数 void Init(int n) int i; numVertex=n; mark=new intn+1; /将所有结点初始化为为被访问的 for(i=0;i=numVertex;i+) marki=UNVISITED; /动态内存分配 matrix=(int *) new int*numVertex+1; for(i=0;i=numVertex;i+) matrixi=new intnumVertex+1; /将所有边权值设为-1,表示无边相连 for(i=0;i=numVertex;i+) for(int j=0;j=numVertex;j+

4、) matrixij=-1; /求顶点数函数 int n() return numVertex; /求第一个邻接点 /求得第一个边并返回顶点编号 int first(int v) int i; for(i=1;i=numVertex;i+) if(matrixvi !=-1)/有边相连 return i; return i; /求下一个邻接点 /求得某个结点的下一个邻接点并返回顶点编号 int next(int v,int w) int i; /因为当前邻接点为w,求下一个的话就是从w+1开始 for(i=w+1;i=numVertex;i+) if(matrixvi!=-1)/有边相连 re

5、turn i; return i; /设置边的权值的函数 void setEdge(int v1,int v2,int wt) matrixv1v2=wt; /将结点v1和结点v2之间的边权值设为wt /查看某个边的权值 int weight(int v1,int v2) return matrixv1v2;/结点v1和结点v2之间的边权值 /查看某个结点是否被访问过 int getMark(int v) return markv;/返回结点v的mark值 /设置某个结点的标志,即是否被访问过 void setMark(int v,int val) markv=val;/将结点v的标志设为va

6、l ; /*= minVertex返回当前到起点距离最小的未被访问的结点。 思路: 首先按顺序找到一个未被遍历的结点; 然后将此结点与后面的结点比较,找到距离最小的结点。 *D数组表示到源结点的距离。Di表示结点i到源结点的距离。=*/int minVertex(Graph &G,int *D) int i; int v=0; for(i=1;i=G.n();i+) /找第一个未被访问的结点 if(G.getMark(i)=UNVISITED) v=i; break; for(i+;i=G.n();i+) /找距源结点距离最小的未被访问的顶点 if(G.getMark(i)=UNVISITED

7、&(DiDv)&Di!=-1)|(Dv=-1) v=i; return v; /*= Dijkstra函数找到当前结点的邻接点,并更新其边权值和祖先节点。 其中记录祖先结点为方便找到路径。* pre数组记录结点的祖先结点。prei表示结点i的祖先结点。D数组表示到源结点的距离。Di表示结点i到源结点的距离。=*/void Dijkstra(Graph &G,int *D,int s,int *pre) int i,v,w; for(i=1;i=G.n();i+) /调用minVertex函数,找到未被访问的距离最小的结点 v=minVertex(G,D); /如果返回的为-1就表示所有结点均被

8、访问过,结束。 if(Dv=-1) return; /将找到的结点置为已访问 G.setMark(v,VISITED); /寻找结点的邻接点更新到起点的距离和祖先结点 for(w=G.first(v); w(Dv+G.weight(v,w)|(Dw=-1) Dw=Dv+G.weight(v,w);/更新到起点的距离 prew=v;/更新祖先结点 测试结果可以看到实现了最短路径与最短路径长度的输出。在我们给定的这个图中使用最短路径算法即Dijkstra算法的时候时间很短,可以看到算法的性质很好。实验心得这个Dijkstra算法真的是学烂了,加起来学了4遍多了。所以对算法的思想还是比较了解的,但是

9、代码编写起来还是有各种问题。还记得上学期第一次学Dijkstra算法的时候,就要做实验写代码,那个时候三个人一个组,然后都花了很久的时间才搞定了一个结构体实现的代码。这次的实现,我选择使用类来实现,与结构体比起来有一个优势就是,结构体实现需要定义两个结构体,另外还需要些很多函数。使用类的话就只用写一个类,然后将函数都写在类里面。虽然使用类和结构体实现不同,但是其大致思路和代码都差不多。但是这个类的实现代码我却写了很久,可能是一开始的时候没有厘清思路,各种初始化没弄好,就一直中断。但是改到最后才发现,其实是因为最主要的一个问题没处理好,就是传递的参数,因为我的图传递的时候没有使用指针,所以就有一

10、个问题,就是在每个函数里对图进行的修改没有办法在调用它的函数中看见,所以一直出现问题,最后一个小小的&符号解决了所有的问题。其实一开始的实现是只能输出最短路径的长度,不能输出最短路径是什么的。但是后来增加了几个数组之后就实现了输出最短路径。这个也要在理解算法思想的基础下才好实现。只要增加数组来记录是哪个结点到当前结点的,即祖先结点。这样进行反向寻找就可以找到路径输出了。通过这次实验,我更加熟练的掌握了Dijkstra算法,相信经过这么多次Dijkstra算法的学习与代码的编写,以后一定可以熟练使用Dijkstra算法。实验得分助教签名附录:完整代码#include#include#includ

11、e#include#include#define UNVISITED 0#define VISITED 1using namespace std;/*=定义图类来存储图的信息。 =*/class Graph private: int numVertex;/图的顶点数 int *matrix; /图的边权值 int *mark; /记录顶点是否被访问 public: /构造函数 Graph(int numVert) Init(numVert); /析构函数 /删除动态分配的内存 Graph() delete mark; for(int i=0;i=numVertex;i+) delete mat

12、rixi; delete matrix; /初始化函数 void Init(int n) int i; numVertex=n; mark=new intn+1; /将所有结点初始化为为被访问的 for(i=0;i=numVertex;i+) marki=UNVISITED; /动态内存分配 matrix=(int *) new int*numVertex+1; for(i=0;i=numVertex;i+) matrixi=new intnumVertex+1; /将所有边权值设为-1,表示无边相连 for(i=0;i=numVertex;i+) for(int j=0;j=numVerte

13、x;j+) matrixij=-1; /求顶点数函数 int n() return numVertex; /求第一个邻接点 /求得第一个边并返回顶点编号 int first(int v) int i; for(i=1;i=numVertex;i+) if(matrixvi !=-1)/有边相连 return i; return i; /求下一个邻接点 /求得某个结点的下一个邻接点并返回顶点编号 int next(int v,int w) int i; /因为当前邻接点为w,求下一个的话就是从w+1开始 for(i=w+1;i=numVertex;i+) if(matrixvi!=-1)/有边相

14、连 return i; return i; /设置边的权值的函数 void setEdge(int v1,int v2,int wt) matrixv1v2=wt; /将结点v1和结点v2之间的边权值设为wt /查看某个边的权值 int weight(int v1,int v2) return matrixv1v2;/结点v1和结点v2之间的边权值 /查看某个结点是否被访问过 int getMark(int v) return markv;/返回结点v的mark值 /设置某个结点的标志,即是否被访问过 void setMark(int v,int val) markv=val;/将结点v的标志

15、设为val ;int minVertex(Graph &G,int *D);void Dijkstra(Graph &G,int *D,int s,int *pre);/*=main函数是主函数。 构造出给定的图的邻接矩阵。进行一些必要的初始化。 之后调用Dijkstra函数,求出最短路径长度,得到记录路径的pre数组。 根据pre数组,求出最短路径。 找出到终点的路径,存储在trave_pre数组中。 因为trave_pre数组中存储的为倒序的路径,所以反向输出即为路径。 =*/ int main() cout=endl; cout=START=endl; cout=endl; Graph

16、G(10); int D11; int pre11; int trave_pre11; int i,j; int start_node; int end_node; /各点至起点的距离初始化为-1 for(i=0;i=G.n();i+) Di=-1; prei=0; trave_prei=0; /有边相连的更新其边值 G.setEdge(1,2,4);G.setEdge(1,3,2);G.setEdge(1,4,5); pre2=1;pre3=1;pre4=1; G.setEdge(2,5,7);G.setEdge(2,6,5); G.setEdge(3,6,9); G.setEdge(4,5

17、,2);G.setEdge(4,7,7); G.setEdge(5,8,4); G.setEdge(6,10,6); G.setEdge(7,9,3); G.setEdge(8,10,7); G.setEdge(9,10,8); /求每个结点的祖先结点 for(int k=1;k=G.n();k+) for(int m=1;m=G.n();m+) if(G.weight(k,m)G.weight(prem,m)&G.weight(k,m)!=-1) prem=k; /输入起点 coutstart_node; /将起点置为已访问 G.setMark(start_node,VISITED); /输

18、入终点 coutend_node; /更新到起点的距离D值 for(int k=1 ; k=G.n() ; k+) Dk=G.weight(start_node,k); /开始计时 clock_t start,end,over; start=clock(); end=clock(); over=end-start; start=clock(); /调用函数 Dijkstra(G,D,start_node,pre); /结束计时 end=clock(); cout=endl; cout=输出结果=endl; cout=endl; /输出路径: cout路径为:=1;t-) if(trave_pr

19、et!=0) couttrave_pret; /输出终点 coutend_nodeendlendl; /输出最短路径多长 cout最短路径为:Dend_nodeendlendl; /输出时间 printf(The time is %6.3fn,(double)(end-start-over)/CLK_TCK); coutendl; cout=endl; cout=END=endl; cout=endl; return 0;/*=minVertex返回当前到起点距离最小的未被访问的结点。 思路: 首先按顺序找到一个未被遍历的结点; 然后将此结点与后面的结点比较,找到距离最小的结点。 *D数组表示

20、到源结点的距离。Di表示结点i到源结点的距离。=*/int minVertex(Graph &G,int *D) int i; int v=0; for(i=1;i=G.n();i+) /找第一个未被访问的结点 if(G.getMark(i)=UNVISITED) v=i; break; for(i+;i=G.n();i+) /找距源结点距离最小的未被访问的顶点 if(G.getMark(i)=UNVISITED&(DiDv)&Di!=-1)|(Dv=-1) v=i; return v; /*=Dijkstra函数找到当前结点的邻接点,并更新其边权值和祖先节点。 其中记录祖先结点为方便找到路径。* pre数组记录结点的祖先结点。prei表示结点i的祖先结点。D数组表示到源结点的距离。Di表示结点i到源结点的距离。=*/void Dijkstra(Graph &G,int *D,int s,int *pre) int i,v,w; for(i=1;i=G.n();i+) /调用minVertex函数,找到未被访问的距离最小的结点 v=minVertex(G,D); /如果返回的为-1就表示所有结点均被访问过,结束。 if(Dv=-1) return; /将找到的结点置为已访问 G.setMark(v,VISITED); /寻找结点的邻接点更新到起点的距离和祖先结点 for(

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1