完整word版dijkstra与floyd方法求最短路径实验报告.docx
- 文档编号:28162817
- 上传时间:2023-07-08
- 格式:DOCX
- 页数:21
- 大小:88.22KB
完整word版dijkstra与floyd方法求最短路径实验报告.docx
《完整word版dijkstra与floyd方法求最短路径实验报告.docx》由会员分享,可在线阅读,更多相关《完整word版dijkstra与floyd方法求最短路径实验报告.docx(21页珍藏版)》请在冰豆网上搜索。
完整word版dijkstra与floyd方法求最短路径实验报告
实验报告
一、实验名称
求最短距离及最短路线。
二、实验目的
(1)掌握最短路径的基础知识,掌握求最短路径的方法。
(2)充分了解Dijkstra算法与Floyd算法的性质与原理。
(3)利用编程的方法求出一个无向图(有向图)中的最短路径。
三、实验内容与要求
求最短距离及最短路线。
1、用Dijkstra算法求从节点1到节点8的最短路,并用程序实现;
2、用Floyd算法求任意两点之间的最短路,并用程序实现;
3、程序实现所用语言不限;
四、实验原理与步骤
(一)Dijkstra算法
1、实验原理:
Dijstra为了算出图中某点到其它点的最短路径,提出了按路径的长度递增次序,逐步产生最短路径的算法,被称为Dijstra算法。
Dijkstra算法采用的是一种贪心的策略,声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:
T,初始时,原点s的路径权重被赋为0(dis[s]=0)。
若对于顶点s存在能直接到达的边(s,m),则把dis[m]设为w(s,m),同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大。
初始时,集合T只有顶点s,然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点加入到T中,此时完成一个顶点,然后,我们需要看看新加入的顶点是否可以到达其他顶点并且看看通过该顶点到达其他点的路径长度是否比源点直接到达短,如果是,那么就替换这些顶点在dis中的值。
然后,又从dis中找出最小值,重复上述动作,直到T中包含了图的所有顶点。
2、实验步骤:
此程序使用了visualstudio2010进行编写,程序参考了《数据结构C++版》课本中的原有程序以及相关知识,并进行了一些改动。
(1)建立一个classDis类,用来记录起点到每个顶点的最短路径的信息。
(2)建立一个Graph_DG类,存放图的顶点和边数、存储图的邻接矩阵以及程序中使用到的函数。
Graph_DG类中的主要函数:
1 析构函数:
用于初始化顶点数和边数。
2 构造函数:
用于释放程序中开辟的内存空间。
3 check_edge_value函数:
判断输入边的数据是否是合法的。
4 creatGraph函数:
创造一个新的图表。
5 print函数:
打印出图的邻接矩阵。
6 Dijkstra函数:
Dijkstra算法的具体实现(利用实验原理中的算法进行程序设计)。
7 Print_path函数:
打印出最小路径以及最小路径的长度。
关于表的输入、打印等函数此处不再赘述。
下面主要叙述Floyd函数的建立:
1 首先初始化dis数组并设置当前的路径;
for(i=0;i
dis[i].path="v"+to_string(static_cast
dis[i].value=arc[begin-1][i];
}
2 设置起点到起点的路径为0;
dis[begin-1].value=0;
3 接下来利用count计算剩余顶点的最短路径,temp用于保存当前dis数组中最小的下标,min记录当前的最小值;
4 把temp对应的顶点加入到已经找到的最短路径的集合中;
5 为防止内存泄漏,此处我们选择加入条件arc[temp][i]!
=INT_MAX的方法;
6 不断更新最短路径和长度总和,直到算出最后结果;
(3)使用一个check函数判断输入的顶点个数和边的条数是否是合法的。
(4)在主函数中建立表类的一个对象,要求用户输入图的顶点、边、边的权值等信息,并使用建立的对象调用上面所写的函数。
(二)Floyd算法
1、实验原理:
利用Floyd计算图G=(V,E)中各个顶点的最短路径时,需要引入两个矩阵,矩阵S中的元素a[i][j]表示顶点i(第i个顶点)到顶点j(第j个顶点)的距离。
矩阵P中的元素b[i][j],表示顶点i到顶点j经过了b[i][j]记录的值所表示的顶点。
假设图G中顶点个数为N,则需要对矩阵D和矩阵P进行N次更新。
初始时,矩阵D中顶点a[i][j]的距离为顶点i到顶点j的权值;如果i和j不相邻,则a[i][j]=∞,矩阵P的值为顶点b[i][j]的j的值。
接下来开始,对矩阵D进行N次更新。
第1次更新时,如果”a[i][j]的距离”>“a[i][0]+a[0][j]”(a[i][0]+a[0][j]表示”i与j之间经过第1个顶点的距离”),则更新a[i][j]为”a[i][0]+a[0][j]”,更新b[i][j]=b[i][0]。
同理,第k次更新时,如果”a[i][j]的距离”>“a[i][k-1]+a[k-1][j]”,则更新a[i][j]为”a[i][k-1]+a[k-1][j]”,b[i][j]=b[i][k-1]。
更新N次之后,操作完成。
2、实验步骤:
本题与Dijkstra算法的程序大部分内容相似,仅有Floyd函数部分做了改动。
同样的,此程序使用了visualstudio2010进行编写,程序参考了《数据结构C++版》课本中的原有程序以及相关知识。
(1)建立一个Graph_DG类,定义图的顶点和边数、存储图的邻接矩阵以及程序中使用到的函数。
Graph_DG类中的主要函数:
1 析构函数:
用于初始化顶点数和边数。
2 构造函数:
用于释放程序中开辟的内存空间。
3 check_edge_value函数:
判断输入边的数据是否是合法的。
4 creatGraph函数:
创造一个新的图表。
5 Floyd函数:
Floyd算法的具体实现(利用实验原理中的算法进行程序设计)。
6 print函数:
打印出图的邻接矩阵。
7 Print_path函数:
打印出最小路径以及最小路径的长度。
关于表的输入、打印等函数此处不再赘述。
下面主要叙述Floyd函数的建立:
1 两个for循环的作用是把矩阵D初始化为邻接矩阵的值,矩阵p的初值则为各个边的终点顶点的下标。
for(i=0;i
for(j=0;j
this->dis[i][j]=this->arc[i][j];
this->path[i][j]=j;
}
}
2 三重循环的作用是计算每个点对的最短路径,在三重循环中进行不断更新D和P矩阵的操作。
for(intm=0;m
for(i=0;i
for(j=0;j
n=(dis[i][m]==INT_MAX||dis[m][j]==INT_MAX)?
INT_MAX:
(dis[i][m]+dis[m][j]);
if(this->dis[i][j]>n){
this->dis[i][j]=n;
this->path[i][j]=this->path[i][m];
}
}
}
}
3 为了防止溢出,我们多引入了一个n值。
n=(dis[i][m]==INT_MAX||dis[m][j]==INT_MAX)?
INT_MAX:
(dis[i][m]+dis[m][j]);
(3)使用一个check函数判断输入的顶点个数和边的条数是否是合法的。
(4)在主函数中建立表类的一个对象,要求用户输入图的类型、顶点、边、边的权值等信息,并使用建立的对象调用上面所写的函数。
五、程序及其运行结果
(一)Dijkstra算法
程序:
#include"StdAfx.h"
#include
#include
usingnamespacestd;
classDis{
public:
stringpath;
intvalue;
boolvisit;
Dis(){
visit=false;
value=0;
path="";
}
};
classGraph_DG{
private:
intvexnum;//图的顶点个数
intedge;//图的边数
int**arc;//邻接矩阵
Dis*dis;//记录各个顶点最短路径的信息
public:
Graph_DG(intvexnum,intedge);
~Graph_DG();
boolcheck_edge_value(intstart,intend,intweight);
voidcreateGraph();
voidprint();
voidDijkstra(intbegin);
voidprint_path(int);
};
Graph_DG:
:
Graph_DG(intvexnum,intedge){//初始化顶点数和边数
this->vexnum=vexnum;
this->edge=edge;
arc=newint*[this->vexnum];
dis=newDis[this->vexnum];
for(inti=0;i
arc[i]=newint[this->vexnum];
for(intk=0;k
arc[i][k]=INT_MAX;
}
}
}
Graph_DG:
:
~Graph_DG(){
delete[]dis;
for(inti=0;i
deletethis->arc[i];
}
deletearc;
}
boolGraph_DG:
:
check_edge_value(intstart,intend,intweight){
if(start<1||end<1||start>vexnum||end>vexnum||weight<0){
returnfalse;
}
returntrue;
}
voidGraph_DG:
:
createGraph(){
cout<<"请输入每条边的起点和终点(顶点编号从1开始)以及其权重"< intstart; intend; intweight; intcount=0; while(count! =this->edge){ cin>>start>>end>>weight; while(! this->check_edge_value(start,end,weight)){ cout<<"输入的边的信息不合法,请重新输入"< cin>>start>>end>>weight; } arc[start-1][end-1]=weight; arc[end-1][start-1]=weight; ++count; } } voidGraph_DG: : Dijkstra(intbegin){ inti; for(i=0;i dis[i].path="v"+to_string(static_cast dis[i].value=arc[begin-1][i]; } dis[begin-1].value=0; dis[begin-1].visit=true; intcount=1; while(count! =this->vexnum){ inttemp=0; intmin=INT_MAX; for(i=0;i if(! dis[i].visit&&dis[i].value min=dis[i].value; temp=i; } } dis[temp].visit=true; ++count; for(i=0;i if(! dis[i].visit&&arc[temp][i]! =INT_MAX&&(dis[temp].value+arc[temp][i]) dis[i].value=dis[temp].value+arc[temp][i]; dis[i].path=dis[temp].path+"-->v"+to_string(static_cast } } } } voidGraph_DG: : print(){ cout<<"图的邻接矩阵为: "< inti=0;//打印行 intj=0;//打印列 while(i! =this->vexnum){ j=0; while(j! =this->vexnum){ if(arc[i][j]==INT_MAX) cout<<"∞"<<""; else cout< ++j; } cout< ++i; } } voidGraph_DG: : print_path(intbegin){ stringstr; str="v"+to_string(static_cast cout<<"以"< "< for(inti=0;i! =this->vexnum;i++){ if(dis[i].value! =INT_MAX) cout< else{ cout< } } } boolcheck(intVexnum,intedge){ if(Vexnum<=0||edge<=0||((Vexnum*(Vexnum-1))/2) returnfalse; returntrue; } intmain(){ intvexnum;intedge; cout<<"输入图的顶点个数和边的条数: "< cin>>vexnum>>edge; while(! check(vexnum,edge)){ cout<<"输入的数值不合法,请重新输入"< cin>>vexnum>>edge; } Graph_DGgraph(vexnum,edge); graph.createGraph(); graph.print(); graph.Dijkstra (1); graph.print_path (1); system("pause"); return0; } 运行结果: (二)Floyd算法 程序: #include"StdAfx.h" #include #include usingnamespacestd; classGraph_DG{ private: intvexnum; intedge; int**arc; int**dis; int**path; public: Graph_DG(intvexnum,intedge); ~Graph_DG(); boolcheck_edge_value(intstart,intend,intweight); voidcreateGraph(int); voidFloyd(); voidprint_path(); voidprint(); }; Graph_DG: : Graph_DG(intvexnum,intedge){ this->vexnum=vexnum; this->edge=edge; arc=newint*[this->vexnum]; dis=newint*[this->vexnum]; path=newint*[this->vexnum]; for(inti=0;i arc[i]=newint[this->vexnum]; dis[i]=newint[this->vexnum]; path[i]=newint[this->vexnum]; for(intk=0;k arc[i][k]=INT_MAX; } } } Graph_DG: : ~Graph_DG(){ for(inti=0;i deletethis->arc[i]; deletethis->dis[i]; deletethis->path[i]; } deletedis; deletearc; deletepath; } voidGraph_DG: : createGraph(intkind){ cout<<"请输入每条边的起点和终点(顶点编号从1开始)以及其权重"< intstart; intend; intweight; intcount=0; while(count! =this->edge){ cin>>start>>end>>weight; while(! this->check_edge_value(start,end,weight)){ cout<<"输入的边的信息不合法,请重新输入"< cin>>start>>end>>weight; } arc[start-1][end-1]=weight; if(kind==2) arc[end-1][start-1]=weight; ++count; } } boolGraph_DG: : check_edge_value(intstart,intend,intweight){ if(start<1||end<1||start>vexnum||end>vexnum||weight<0){ returnfalse; } returntrue; } voidGraph_DG: : Floyd(){ inti=0,j=0; for(i=0;i for(j=0;j this->dis[i][j]=this->arc[i][j]; this->path[i][j]=j; } } intm=0,n=0; for(intm=0;m for(i=0;i for(j=0;j n=(dis[i][m]==INT_MAX||dis[m][j]==INT_MAX)? INT_MAX: (dis[i][m]+dis[m][j]); if(this->dis[i][j]>n){ this->dis[i][j]=n; this->path[i][j]=this->path[i][m]; } } } } } voidGraph_DG: : print(){ cout<<"图的邻接矩阵为: "< inti=0;//i代表打印行 intj=0;//j代表打印列 while(i! =this->vexnum){ j=0; while(j! =this->vexnum){ if(arc[i][j]==INT_MAX) cout<<"∞"<<""; else cout< ++j; } cout< ++i; } } voidGraph_DG: : print_path(){ cout<<"各个顶点对的最短路径: "< inti=0; intj=0; intm=0; for(i=0;i for(j=i+1;j cout<<"v"< " < "<<"v"< m=path[i][j]; while(m! =j){ cout<<"-->"<<"v"< m=path[m][j]; } cout<<"-->"<<"v"< } cout< } } boolcheck(intVexnum,intedge){ if(Vexnum<=0||edge<=0||((Vexnum*
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 完整 word dijkstra floyd 方法 求最短 路径 实验 报告