实验9最短路径问题.docx

上传人:b****5 文档编号:6872374 上传时间:2023-01-11 格式:DOCX 页数:15 大小:319.02KB
下载 相关 举报
实验9最短路径问题.docx_第1页
第1页 / 共15页
实验9最短路径问题.docx_第2页
第2页 / 共15页
实验9最短路径问题.docx_第3页
第3页 / 共15页
实验9最短路径问题.docx_第4页
第4页 / 共15页
实验9最短路径问题.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

实验9最短路径问题.docx

《实验9最短路径问题.docx》由会员分享,可在线阅读,更多相关《实验9最短路径问题.docx(15页珍藏版)》请在冰豆网上搜索。

实验9最短路径问题.docx

实验9最短路径问题

最短路径问题及解法

一、实验目的 

1.了解求解最短路径的Dijkstra算法和Floyd算法的基本原理;

2.掌握Dijkstra算法和Floyd算法的基本步骤;

3.能应用相关的算法求解实际问题

4.掌握Dijkstra算法和Floyd算法的C程序设计技巧;

2、实验内容

1.求解最短路径的Dijkstra算法及C程序实现

2.求解最短路径的Floyd算法及C程序实现

1.

求解最短路径问题的Dijkstra算法

问题1:

已知如图1所示的单行线交通网,它是一个有向图,每条弧旁的数字表示这条单行线的长度.现在某人要从

出发,通过这个交通网到

去,求使下图中总路程最小的路径.

图1

引入基本变量:

ωij:

各边的权数,

d(v1,vj):

v1到vj的路的总权数的最小值

P标号:

从v1到vj的最短路径的权数已确定

T标号:

从v1到vj的最短路径的权数的上界

Si:

算法进行到第i步时,具P标号点的集合.

λ(v)=m:

从vs到v的最短路上,v的前一个点是vm,λ(v)=0,则v=vs.

λ(v)=M:

D中不含从vs到v的路;

1.1结合图表演示Dijkstra算法的基本步骤和基本原理

我们用图表结全的方法讲述Dijkstra算法的基本步骤

第一步

因ωij≥0,故d(v1,v1)=0.v1加上P标号(图2中用划圈表示).

图2

表1第一步

被圈去的次序

顶点

从v1到该点的最短路的长度

该节点的前一个节点

1

v1

0

起点

v2

v3

v4

v5

v6

v7

v8

v9

第二步:

从v1共发出3条弧,(v1,v2),(v1,v3),(v1,v4).

若从v1出发沿(v1,v2)到达v2,权数为d(v1,v1)+ω12=6;

若从v1出发沿(v1,v3)到达v3,权数为d(v1,v1)+ω13=3;

若从v1出发沿(v1,v4)到达v4,权数为d(v1,v1)+ω14=1.

min{d(v1,,v1)+ω12,d(v1,v1)+ω13,d(v1,v1)+ω14}

=min{6,3,1}

=d(v1,v1)+ω14=1

故从v1出发到v4的路径的最小权必为1,最短路是(v1,v4),

d(v1,v4)=1,

给v4加上P标号(图3中加圈表示).为什么?

图3

表2第二步

加P标号的次序

顶点

从v1到该点的最短路的长度

该节点的前一个节点

1

v1

0

起点

v2

6

v1

v3

3

v1

2

v4

1

v1

v5

v6

v7

v8

v9

 

第三步:

加上红圈的点表示具有P标号,现考查从v1及v4指向其余点的弧

从v1出发,分别沿(v1,v2)、(v1,v3)到达v2,v3,权数分另别为6和3,

从v4出发,沿(v4,v6)到达v6,权数为d(v1,v4)+ω46=1+10=11,

min{d(v1,v1)+ω12,d(v1,v1)+ω13,d(v1,v4)+ω46}

=min{6,3,11}

=d(v1,v1)+ω13=3

故从v1到v3的最短路是(v1,v3),

d(v1,v3)=3,

v3加上P标号.

图4

表3第3步

加P标号的次序

顶点

从v1到该点的最短路的长度

该节点的前一个节点

1

v1

0

起点

v2

6

v1

3

v3

3

v1

2

v4

1

v1

v5

v6

11

v4

v7

v8

v9

 

第四步:

加上红圈的点表示具有P标号,现考查从v1,v3和v4发出的弧.

从v1出发,沿(v1,v2)到达v2总权数为d(v1,v1)+ω12=6,

从v3出发,沿(v3,v2)到达v2总权数为d(v1,v3)+ω32=5,

5<6,因此到达v2的路径长度的上界应改为5,v2的前一个节点也应改为v3.

从v3出发,沿(v3,v4)到达v4,因v4已具有P标号,不再参与计算.

从v4出发,沿(v4,v6)到达v6权数为d(v1,v4)+ω46=1+10=11,

min{d(v1,v1)+ω12,d(v1,v3)+ω32,d(v1,v4)+ω46}

=min{6,5,11}

=d(v1,v1)+ω13=3

故从v1到v2的最短路是(v1,v3,v2),

d(v1,v2)=5,

v2加上P标号.

图5

表4第4步

加P标号的次序

顶点

从v1到该点的最短路的长度

该节点的前一个节点

1

v1

0

起点

4

v2

6,5

v1 , v3

3

v3

3

v1

2

v4

1

v1

v5

v6

11

v4

v7

v8

v9

按照同样的方法,重复这个过程即可得到从v1出发到v8的最短路,最终的表格如下:

表5最终表格

加P标号的次序

顶点

从v1到该点的最短路的长度

该节点的前一个节点

1

v1

0

起点

4

v2

6,5

v1 , v3

3

v3

3

v1

2

v4

1

v1

5

v5

6

 v2

7

v6

11,10

v4 , v5

6

v7

9

 v5

8

v8

12

 v5

v9

从表中我们可以到得从从v1出发到v8的最短路的长度为12,具体路短为:

v8←v5←v2←v3←v1.

1.2Dijkstra算法的算法描述

上文介绍的这个算法即为Dijkstra(迪杰斯特拉)算法,它是典型的单源最短路径算法,可用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.对于给定的赋权有向图D=(V,A)(或无向图D=(V,E)),欲求从vs出发到vt的最短路径(链),Dijkstra方法的具体步骤如下:

Step0 :

令i=0,  S0={vs},P(vs)=0,λ(vs)=0,对每一个v≠vs,令T(v)=+∞,λ(v)=M,令k=s.

Step1 :

  如果vt

Si,算法终止,对每个v∈Si,d(vs,v)=P(v);否则转下一步.

Step2 :

考查每个使(vk,vj)∈A且vk

Si的点vj.

如果T(vj)>P(vk)+wkj,则把T(vj)修改为P(vk)+wkj,把λ(vj)修改为k;

否则转下一步.

Step3:

如果

,则把

的T标号变为P标号,

 

若目标终点出现在Si+1中, 终止,这时

(I)对每一个v∈Si,d(vs,v)=P(v),

(II)对每一个

,d(vs,v)=T(v).

否则令i= i+1,转入Step1.

1.3Dijkstra算法的C程序实现

我们编写了Dijkstra算法的C语言程序,并将程序应用于求解问题1,程序见附件,程序运行结果如下:

/*Dijkstra算法,键盘输入起点和终点,以图1.1的问题为例*/

#include

#defineMIN(x,y)(x<=y?

x:

y)

voidmain()

{

doublea[10][10],v[10][3],t;

inti,j,k,n=9,m,i0,m0;

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

a[i][j]=-1;

for(i=0;i<=9;i++)

for(j=0;j<=2;j++)

v[i][j]=-1;

//邻接矩阵

a[1][2]=6;a[1][3]=3;

a[1][4]=1;a[2][5]=1;

a[3][2]=2;a[3][4]=2;

a[4][6]=10;a[5][4]=6;

a[5][6]=4;a[5][7]=3;

a[5][8]=6;a[6][5]=10;

a[6][7]=2;a[7][8]=4;

a[9][8]=3;a[9][5]=2;

//i0:

起点下标,m0:

终点下标;

puts("Pleaseinputtheindexofthestaringpoint:

");

scanf("%d",&i0);

puts("Pleaseinputtheindexofterminalpoint:

");

scanf("%d",&m0);

i=i0;

m=m0;

n=9;//点的总数

v[i][0]=0;//起点到起点的距离设为0

v[i][1]=1;//划圈的点置值1,其余为-1

v[i][2]=0;//前一个点的编号

while

(1)

{

for(j=1;j<=n;j++)

{

if(v[j][1]>0)continue;

t=a[i][j];

if(t<0.0)continue;

t+=v[i][0];

if(v[j][0]<0)

{

v[j][0]=t;

v[j][2]=i;

}

elseif(t

{

v[j][0]=t;

v[j][2]=i;

}

}

t=1.0e20;

for(j=1;j<=n;j++)

{

if(v[j][1]>0||v[j][0]<0)continue;

if(v[j][0]

{

t=v[j][0];

k=j;

}

}

v[k][1]=1.0;

i=k;

if(k==m)break;

}

for(j=1;j<=n;j++)

printf("%3d--%5.2f--%5.2f--%5.2f\n",j,v[j][0],v[j][1],v[j][2]);

printf("Theleastchainis:

%d",m);

while

(1)

{

k=(int)(v[m0][2]);

printf("<--%d",k);

m0=k;

if(k==i0)break;

}

puts("");

}

 

练习:

(1)编程实现用Dijkstra方法求下面的无向图中从v1到其它某个节点的距离的最小值,要求其它某节点待定,其序号由键盘输入。

图6

(2)思考如何设计一个有类似于高德地图等手导航功能的程序。

 

2.求解最短路径的Floyd算法

1.2Floyd算法的基本思想

Floyd-Warshall算法(Floyd-Warshallalgorithm)是解决网络图中任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包. Floyd算法是一个经典的动态规划算法.

从任意节点A到任意节点B的最短路径不外乎2种可能:

1)直接从A到B,

2)从A经过若干个节点X到B.

我们假设dis(A,B)为节点A到节点B的最短路径的长度,对于每一个节点X,我们检查

dis(A,X)+dis(X,B)

是否成立,如果成立,证明从A到X再到B的路径比从A直接到B的路径更短,我们便设置

dis(A,B)=dis(A,X)+dis(X,B).

这样一来,当我们遍历完所有节点X,Dis(A,B)中记录的便是A到B的最短路径的距离.

2.2Floyd算法的基本步骤

Step1用数组dis[i][j]来记录

之间的最短距离;

Step2初始化dis[i][j];

若i=j则dis[i][j]=0,

之间有边连接则dis[i][j]的值为该边的权值,

否则dis[i][j]的值为无穷大.

Step3对k从1到n循环,不断修正任意两点之间的最短距离.若

dis[i][k]+dis[k][j]

则令dis[i][j]=dis[i][k]+dis[k][j],否则dis[i][j]的值不变.

2.3Floyd算法的正确性的证明

对于任意两点A,B:

(1)当从A到B之间的最短路径,在中间没有经过节点或经过1个节点号为1的节点时,算法显然正确.

(2)假设A到B经过的最大节点号不超过k-1时,算法得到的最短距离是正确的

(3)当A到B的路径上经过的最大节点下标为k时,则从A到节点

之间的节点号均不大于k-1,从

到B之间所有的节点号也不大于k-1,由假设2得,A到

的距离是中间节点号不超过

的最短距离,

到B的距离是中间节点号不超过k-1的最短距离,所以A经

到B为A,B之间经节点最大编号为k的路径中距离的最小值,由算法修正A,B的最短距离,即可得到A,B间节点编号不超过k的距离的最小值.

(4)综上所述,算法是正确的

 

2.4Floyd算法的C程序实现

我们编写了Floyd算法的C语言程序求解问题1,程序见附件,程序运行结果如下:

//Floydmethod,以图1.1中的问题为例

#include

#defineMIN(x,y)(x<=y?

x:

y)

voidmain()

{

doublea[10][10],t;

inti,j,k,n,m,i0,m0,path[10][10];

n=9;

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

a[i][j]=1.0e10;

for(i=0;i<=n;i++)

for(j=0;j<=9;j++)

path[i][j]=j;

for(i=0;i<=n;i++)

a[i][i]=0;

a[1][2]=6;a[1][3]=3;

a[1][4]=1;a[2][5]=1;

a[3][2]=2;a[3][4]=2;

a[4][6]=10;a[5][4]=6;

a[5][6]=4;a[5][7]=3;

a[5][8]=6;a[6][5]=10;

a[6][7]=2;a[7][8]=4;

a[9][8]=3;a[9][5]=2;

for(k=1;k<=n;k++)

for(i=1;i<=n;i++)

for(j=1;j<=n;j++)

if(a[i][j]>a[i][k]+a[k][j])

{

a[i][j]=a[i][k]+a[k][j];

path[i][j]=path[i][k];

}

puts("Thematrixa[][]:

");

for(i=1;i<=n;i++)

{

for(j=1;j<=n;j++)

printf("%5.1f",a[i][j]);

puts("");

}

puts("Thematrixpath[][]:

");

for(i=1;i<=n;i++)

{

for(j=1;j<=n;j++)

printf("%3d",path[i][j]);

puts("");

}

//i0:

起点下标,m0:

终点下标;

puts("Pleaseinputtheindexofthestaringpoint:

");

scanf("%d",&i0);

puts("Pleaseinputtheindexofterminalpoint:

");

scanf("%d",&m0);

printf("Thelengthofthebestpathis:

%f\n",a[i0][m0]);

printf("Thebestpathis:

\n");

while(m0!

=i0)

{

printf("%d-->",i0);

i0=path[i0][m0];

}

printf("%d\n",m0);

}

练习:

(1)编程实现用Floyd方法求下面的无向图中从v1到其它某个节点的距离的最小值,要求其它某节点待定,其序号由键盘输入。

图6

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科

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

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