网络原理实验报告Dijkstra.docx
《网络原理实验报告Dijkstra.docx》由会员分享,可在线阅读,更多相关《网络原理实验报告Dijkstra.docx(13页珍藏版)》请在冰豆网上搜索。
网络原理实验报告Dijkstra
网络原理实验报告
——编程实现Dijkstra路由算法
姓名:
班级:
学号:
教师:
1.实验目的
运用各种编程语言实现基于Dijkstra算法的路由软件。
PS:
这里使用的是JAVA语言
2.实验意义
通过本实验,使学生能够对路由原理和路由算法有进一步的理解和掌握。
3.实验背景
Dijkstra算法描述如下:
设:
c(i,j):
结点i至结点j之间链路的代价,若i,j不直接相连,则为无穷大。
D(v):
当前从源结点至目的结点V之间路由的代价。
p(v):
从源结点至目的结点V之间路由中V之前的结点
N:
已经知道最优路径的结点集合
1Initialization:
2N={A}
3forallnodesv
4ifvadjacenttoA
5thenD(v)=c(A,v)
6elseD(v)=infty
7Loop
8findwnotinNsuchthatD(w)isaminimum
9addwtoN
10updateD(v)forallvadjacenttowandnotinN:
11D(v)=min(D(v),D(w)+c(w,v))
12/*newcosttoviseitheroldcosttovorknown
13shortestpathcosttowpluscostfromwtov*/
14untilallnodesinN
4.实验步骤
(1)选择合适的编程语言编程实现基于Dijkstra算法的路由软件。
(2)输入不同的网络拓扑和链路代价测试和验证自己的路由软件。
5.实验环境
(1)实验语言:
JAVA
(2)实验平台:
Eclipse
(3)引用库函数:
随机(Random)库
6.算法思想理解与描述
在编写代码时,我曾遇到过两个问题也是最容易碰到的难题,这里我介绍一下自己的解决方法:
A.Dijkstra算法究竟是怎样计算最短距离和最短路径的?
也许如果只是要我们写一个算法,求最短路径和最小距离,那么我们可能不同的人有不同的“自然而然”的思路,而且肯定很多并不与Dijkstra算法雷同,但令我们头疼的是:
这里是别人写好了一个算法,我们得去理解,而不是让我们自己去操刀。
在我看来,与其看那些枯燥无味的算法文字叙述还不如看图看表——
我就是看了(中文版)P240的表4-3(它对应着P238的图4-27)才明白是“怎么算的”,这里我就说下自己的理解,也不过就是几句话而已:
1.一开始,将源节点到各点的直达距离作为最短距离;
PS:
这里还是要理解表中D()和p()的含义——D()就是刚才说的到目标节点的“目前认为”的最短距离,而p()是“当前认为”的最短路径上到目标节点的前一节点(至少我是这么认为的:
如果只求最短距离,p()是不需要的,p()的作用是最后用来“逆推”出最短路径!
)
2.取最小的D()值那个节点,我们“假装”认为它是最短的距离。
PS:
这里书上说添到一个新的集合中,其实我觉得为了达到算法目的,不要这个集合也行,只要做到以下两点:
(1)下一行选最小D()值时不把之前选过的节点考虑在内
(2)每一行D()的更新只需要做到对剩下每一个D()检查一次更新即可
3.到新的一行(也就是每次循环)就对剩下(还没有选过的节点)的D()做一个检查更新,方法也很简单:
假设源节点为A,目标节点为B,上一行(循环)选中的节点为C,那么D(B)=min{D(B),distance(C,B)+D(C)}
4.重复2、3步骤(循环)——循环何时终止呢?
大家看表4-3就会明白循环次数就是节点的个数
5.得到了最短距离后如何得到最短路径呢?
这个时候p()就派上用场了,方法也很简单,逆推即可:
设源节点是A,目标节点是B,路径就该是
B←p(B)←p(p(B))←……←A
B.知道了Dijkstra算法的设计思想后,怎么编程呢?
!
我们编程最容易遇到的问题莫过于此:
一个算法用数学语言或者人类自然语言比较容易描述和理解,但是代码(机器语言)却很难把简单的一段话实现,但是如果按照前面讲过的几个要点依次来编写就是很容易的,这里就谈谈关键的几个步骤吧:
1.“图”的绘制——想必大家都是手工输入节点和任意两条边间的距离吧?
不说太夸张的,如果我有15个节点,有50条边,估计手指按键盘都得按疼(100个节点,300条边更不说了)
这里,我听取了学长的建议,无论是节点的名称、节点的个数、源节点的选取还是边的权值都用系统随机数设置(这里比如还可以设随到-1的话表示无穷大)——这就是全自动化的好处,再也不用担心手疼了!
因此,我选择使用JAVA里的随机类Random,一方面是方便省心省力另一方面“AllRandom”(全随机)更能帮你检查算法正确性以及更加符合实际
2.选D()最小值:
自己写一个求数组最小值的min()函数就可以了,每次求D()最小值是要排除已经选过的节点的,怎么实现呢?
——可以把选过的节点的D()值用另一个数组的元素暂存起来,然后自己被赋成∞,这样min{D(Vi)}就不会出现重复了
3.D()值更新——其实也就是算法最精华的部分,采用判断语句就可以了:
数学表达:
D(B)=min{D(B),distance(C,B)+D(C)}
代码表达:
D[i]=D[i]D[i]:
dis[k][i]+D[k]
或者if+else语句也行
4.最佳路径的查找——也就是迭代
我们可以使用while语句进行,终止条件就是迭代得到的节点是源节点就可以了,例如目标节点是D,源节点是A那么由p(D)得到了C,再由p(C)得到B,再有p(B)得到A,迭代终止——我们可以以此得到DCBA,颠倒顺序就可以得到最短路径ABCD了!
7.类概览与描述
(1)Grap类:
自定义的“图”类,用于模拟各个路由器(节点)和各条链路(边),主要功能函数如下:
PublicGrap(String[]v)——自定义的构造函数,主要功能有:
A.接收随机定义好的(名字和数量都是由系统随机指定的)顶点集
B.对顶点集经行初始化并且初始化任意两个定点间的距离值(如果不可直达则为无穷大),这里的距离值(即权值)是由系统随机数指定的
C.依次显示路由器数量、名称、各路由器到其他路由器的距离值
D.统计非无穷大边(有限权值边)的数量并显示
(2)Dijkstra类:
主函数类,实现核心功能,主要功能函数有:
A.Publicstaticintmin(int[]a)——最小值函数,获取一个指定的整型数组中最小值对应的数组下标
B.PublicstaticString[]closestpath(String[]route,String[]p,intstar)——路径计算函数,该函数是建立在已经计算得到最小距离之上的,用字符串数组依次保存源节点到各目标节点的最短路径上的路由器名称
C.Publicstaticvoiddijkstra(Grapg,Stringstar)——Dijkstra算法中求找最小距离的功能函数,运行结果依次显示源节点到各目标节点的最小距离和对应的最短路径
D.Publicstaticvoidmain(String[]args)——主函数,用于程序的初始化(比如随机顶点集的初始化)和程序算法的执行(调用各功能函数)
8.代码展示与描述
(一)Grap类
importjava.util.Random;
publicclassGrap{
String[]route;
int[][]distance;
intcount=0;
publicGrap(String[]v){
route=v;//获取顶点集
distance=newint[route.length][route.length];//用二维数组保存任意两条边的距离
System.out.print("【随机】设置了"+v.length+"个路由器");//统计路由器总数
System.out.print("路由名分别为:
");
for(inti=0;i{System.out.print(v[i]);System.out.print("");//依次显示路径名称
System.out.println();
for(inti=0;ifor(inti=0;iSystem.out.print("【随机】路由"+route[i]+"到其他路由的距离依次为:
");
for(intj=i+1;jintran=newRandom().nextInt(150);//设定随机值
if(ran>100){//设置一定的概率出现“无穷大”distance[i][j]=10000;
System.out.print("∞");
distance[j][i]=distance[i][j];
}
else{
distance[i][j]=ran;
System.out.print("");
System.out.print(ran);//依次显示每个顶点到其他顶点的距离
distance[j][i]=ran;
count++;
}
}
System.out.println();
}
System.out.print("【统计】本架构中总共有:
");//统计有限权值边的条数
System.out.print(count);
System.out.print("条边!
");
}
}
(二)Dijkstra类
importjava.util.Random;
publicclassDijkstra{
publicstaticintmin(int[]a){//返回数组中的最小值的下标
intmin=a[0];
intminsign=0;
for(inti=0;iif(a[i]!
=0){
if(a[i]min=a[i];
minsign=i;
}
}
}
returnminsign;//min表示最小值,minsign表示对应的元素下标
}
publicstaticString[]closestpath(String[]route,String[]p,intstar){//计算各条最短路径并且保存于字符串数组中
intnum=route.length;//获取节点数
intsorce=star;//获取源节点
String[]vname=route;//获取顶点集
String[]path=newString[num];//路径
for(inti=0;ipath[i]=vname[i]+"";
Stringp1="AB";
for(inti=0;iif(i!
=sorce){
p1=p[i];//采用逆推思维,从后向前依次表示
path[i]+=p1+"";
while(p1!
=null&&(!
p1.equals(vname[sorce]))){//逆推至源节点表示最短路径完全确定了
for(intt=0;tif(vname[t].equals(p1))
p1=p[t];
}
path[i]+=p1+"";
}
}
}
String[][]path01=newString[num][];//以下部分均是路径显示格式的调整与转换
String[]truepath=newString[num];
for(inti=0;ifor(inti=0;ipath01[i]=path[i].split("");
for(inti=0;ipath01[i][path01[i].length-1]=route[sorce];
for(inti=0;ifor(intj=path01[i].length-1;j>=0;j--){
if(path01[i][j]!
=null)
truepath[i]+=path01[i][j]+"";
}
}
for(inti=0;itruepath[i]=truepath[i].replaceAll("","→");
truepath[i]=truepath[i].substring(0,truepath[i].length()-1);
}
returntruepath;
}
publicstaticvoiddijkstra(Grapg,Stringstar){//获取源节点到各节点最小距离的算法
intvnum=g.route.length;//获取节点数
Stringsource=star;//获取源节点
String[]v=g.route;//获取顶点集
int[][]dis=g.distance;//获取任意两点间距离值(权值)
intsorce;
for(sorce=0;sorceif(v[sorce].equals(source))
break;//锁定源节点
int[]D=newint[vnum];//用来表示源节点到目标节点当前的最短距离
String[]p=newString[vnum];//表示源节点到目标节点当前最短路径上的前一节点
int[]closest=newint[vnum];//存放最短距离
for(inti=0;iclosest[sorce]=0;
for(inti=0;iif(i!
=sorce){
D[i]=dis[sorce][i];//初始化dijkstra算法表第一行
p[i]=source;
}
}
D[sorce]=10000;
intsv=1;//标志当前已经纳入集合的节点个数
while(svintsign=min(D);//获取所有距离值中最小的一个的路由器下标
sv++;//把该节点加入到集合中;
for(inti=0;iif(i!
=sorce&&D[i]!
=9999){//已经考虑过的节点不再考虑范围内
if(D[i]>dis[sign][i]+D[sign]){
D[i]=dis[sign][i]+D[sign];//更新最小距离的表
p[i]=v[sign];//更新最短路径的前一个节点
}
}
}
closest[sign]=D[sign];
D[sign]=9999;
}
String[]closestpath=closestpath(v,p,sorce);//在获得了最小距离后,立刻求找对应的最短距离
for(inti=0;iif(i!
=sorce&&closest[i]<9999){//显示源节点到各目标节点的最小距离和最短路径
System.out.print("【计算】路由"+source+"到路由"+v[i]+"的最短距离是"+closest[i]);
System.out.print("");
System.out.print("最短路径为:
"+closestpath[i]);
System.out.println();
}
else{
if(!
source.equals(v[i])){//若不可达给予显示
System.out.print("【计算】路由"+source+"不能到达路由"+v[i]);
System.out.println();
}
}
}
}
publicstaticvoidmain(String[]args){
intnum=0;
while(num==0)num=newRandom().nextInt(22);//设定路由器数量的随机值
String[]route=newString[num];//初始化顶点集
for(inti=0;iGrapg=newGrap(route);//初始化图
intsorce=newRandom().nextInt(num);//随机选取源节点
System.out.println("【随机】选取的源节点是路由"+route[sorce]);
dijkstra(g,route[sorce]);//运行Dijkstra算法
}
}
9.程序运行结果部分截图