5.4.2图的应用(最短路径)

5.4.2图的应用(最短路径)

[外链图片转存失败(img-n86sdQ3v-1566916471884)(assets/1566913805910.png)]

[外链图片转存失败(img-EWBlyRHc-1566916471885)(assets/1566913904982.png)]

迪杰斯特拉:

用集合S来记录以求得最短路径得顶点,可以用一个数组来是s[]来实现,初始化为0,当s[vi]=1时表示vi加入S中,初始化把源点v0放入S中。此外,在构造过程中还设置了两个辅助数组:

dist[]:记录了从源点到顶点i之间的最短路径长度,dist[]初值为arcs[v0][i]

path[]:记录path[i]表示从源头到顶点i之间得最短路径得前驱结点,在算法结束时,可根据其值追溯到源点v0到vi最短路径。

算法思想:

假设从顶点0出发 ,也就是顶点V0为源点,集合S最初只包含顶点0,邻接矩阵Arcs表示带权有向图,Arcs[i][j]表示有向边<i,j>权值,若不存在有向边<i,j>,则arcs[i][j]=无穷。

算法步骤:

1)初始化:集合S初始为{0},dist[]得初始值dist[i]=arcs[0][i],i=0,1,2,…n-1。

2)找出dist[]中最小的值dist[j]将顶点j加入集合S,即修改s[vj]=1。

3)修改从vo出发到集合V-S上任意顶Vk可达得最短路径长度:如果dist[j]+arcs[j][k]<dist[k],则dist[k] =dist[j]+arcs[j][k],另外更新path[k]=j。

4)重复2)3)操作n-1次,直到所有的顶点都包含在S中。

[外链图片转存失败(img-iTJX1DRG-1566916471886)(assets/1566914987903.png)]

[外链图片转存失败(img-2KHsKzo0-1566916471887)(assets/1566915003182.png)]

[外链图片转存失败(img-oqbZhmK3-1566916471887)(assets/1566915155837.png)]

[外链图片转存失败(img-6tsQuyaM-1566916471888)(assets/1566915059224.png)]

[外链图片转存失败(img-LrNaLkpB-1566916471888)(assets/1566915071566.png)]

[外链图片转存失败(img-Wb2nM2wO-1566916471889)(assets/1566915088909.png)]

由于只剩顶点6所以直接加入顶点6并修改s[6]=1。

[外链图片转存失败(img-9TkiXayp-1566916471889)(assets/1566915111072.png)]

[外链图片转存失败(img-R12pGkUP-1566916471890)(assets/1566915302911.png)]

算法代码:

void Dijikstra(MGraph G ,int path[],int dist[]){//v是源点下标
    int s[MaxSize]; 
    int i,j,min,u;
    for(i=0;i<G.vexnunm;i++){
		dist[i]=G.edge[v][i];  
        s[i]=0;
        if(G.Edge[v]<65535)
            path[i]=v;
        else
            path[i]=-1;
    }
    s[v]=1; //源点加入集合S
    path[v] =-1;//源点不存在到自身的路径
    //@1:内层第一个循环是找到剩余顶点中距离最小的顶点u并把它加入最短路径
    //@2:内层第二个循环是由新加入的顶点u来判断是否找到了新的更新路径,如果有就操作,没有就不操作
    for(i=0;i<G.vexnum;i++){
		min =65535;
        for(j=0;j<g.vexnum;j++){
            if(s[j]==0&&dist[j]<min){
				u=j;
                 min=dist[j];
            }
        }
        s[u]=1;  //到u的距离最短,所以顶点u加入最短路径
      	for(j=0;j<G.vexnum;j++){
			if(s[j]==0&&dist[u]+G.Edege[u][j]<dist[j]){
				dist[j]=dist[u]+G.Edege[u][j];
                 path[j]=u;//这条较短的路径是由顶点u过来的
            }
        }
    }

}

时间复杂度:

核心部分有一个双重循环,这个双重循环的内循环又是两个并列的单重for循环组成(找距离最小点和更新距离),所以时间复杂度为O(n^2)其中n为图中定点数。

note:迪杰斯特拉算法不能用于权值有负数的图,不然会出错。
[外链图片转存失败(img-BSCulbx9-1566916471890)(assets/1566916425906.png)]

弗洛伊德(多源点)

求图中任意一对顶点间的最短路径

算法思想:

递推产生一个n阶方阵序列A(-1),A(0),A(1),…A(n-1)

其中A(K)[i][j]表示任意顶点vi和vj的路径长度,k表示绕行第k个顶点的运算步骤。

初始时,对于任意两个顶点vi和vj,若它们之间存在边,则此边上第权值作为他们之间的最短路径;若不存在,则以无穷作为它们之间的最短路径长度,以后逐步尝试在原路径中加入顶点k(k=0,1,2,…n-1)作为中间结点。如果增加中间结点后,得到的路径比原来的路径长度减少了,则以此新路径代替原路径。

[外链图片转存失败(img-tdqCFYlK-1566963337805)(assets/1566962142712.png)]

维护两个矩阵 A(记录两个点之间的最短路径) 和Path(记录两个顶点将最短路径上要经过的中间结点)

[外链图片转存失败(img-aqDFPWgq-1566963337808)(assets/1566962290579.png)]

note:每一轮,我们选取那个顶点为中间结点时,不需要考虑它所在的行和列还有主对角线上的最短路径的变化。

[外链图片转存失败(img-B9JsHeN3-1566963337809)(assets/1566962579141.png)]

[外链图片转存失败(img-n15ckIZG-1566963337809)(assets/1566962593323.png)]

[外链图片转存失败(img-tkT4fKE6-1566963337810)(assets/1566962604922.png)]

[外链图片转存失败(img-7LyoqPjG-1566963337811)(assets/1566962614180.png)]

执行完毕。

代码:

void Floyd(MGraph G,int Path[][]){
	int i,j,k;
    int A[MaxSize][MaxSzie];
    for(i=0;i<G.vexnums;i++){
       	for(j=0;j<G.vexnums;j++){
			A[i][j]=G.Edges[i][j];
             Path[i][j]=-1;
        }
    }
    for(k=0;k<G.vexnums;k++){
        for(i=0;k<G.vexnums;i++){
            for(j=0;k<G.vexnums;j++){
				if(A[i][j]>A[i][k]+A[k][j]){
					A[i][j]=A[i][k]+A[k][j];
                      Path[i][j]=k;
                }
            }
        }
    }
}

时间复杂度:核心为三重循环所以时间复杂度为O(n^3),n是顶点数。

note:迪杰斯特拉算法和弗洛伊德算法时间复杂度比较,由于迪杰斯特拉时单源点,而弗洛伊德为多源点所以迪杰斯特拉时间复杂度为O(n^2),如果要求所有顶点当作源点,需要*O(n),所以说两个算法的时间复杂度差不多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值