最小生成树和最短路径

最小生成树

生成树概念:
一个连通图的生成树是一个极小连通子图,它含有图中全部n个顶点和构成一棵树的(n-1)条边。
在这里插入图片描述
可以通过遍历方法产生生成树:

  • 由深度优先遍历得到的生成树称为深度优先生成树。

在这里插入图片描述

  • 由广度优先遍历得到的生成树称为广度优先生成树。

在这里插入图片描述
最小生成树概念:

  1. 对于带权连通图G (每 条边上的权均为大于零的实数),可能有多棵不同生成树。
  2. 每棵生 成树的所有边的权值之和可能不同。
  3. 其中权值之和最小的生成树称为图的最小生成树。

普里姆(Pim)算法

用普里姆(Pim)算法构造过程:
(1)初始化U={v}。v到其他顶点的所有边为候选边;
(2) 重复以下步骤n-1次,使得其他n-1个顶点被加入到U中:
➊从候选边中挑选权值最小的边输出,设该边在V-U中的顶点是k,将
k加入U中;
❷考察当前V-U中的所有顶点,修改候选边:若(, k)的权值小于原来
和顶点k关联的候选边,则用(k, j)取代后者作为候选边。
在这里插入图片描述
算法演示:
在这里插入图片描述
在这里插入图片描述
。。。。。。。。
在这里插入图片描述
在这里插入图片描述
从上面的流程我们可以知道:先将出发点0存在一个集合U,然后其余的存在另一个集合V-U,然后在这两个集合中选择一条最小边添加到T中,然后依次操作直到U中包含所以顶点。

这里算法就不给出来,但要知道的是改算法中有两重for循环, 所以时间复杂度为O(n²)。该算法的执行时间与图中边e无关,所以它适合于稠密图求最小生成树。

克鲁斯卡尔(Kruskal)算法

克鲁斯卡尔(Kruskal)算法是按权值的递增次序选择合适的边来构造最小生成树的方法。

算法构造过程:
(1)置U的初值等于V (即包含有G中的全部顶点), TE的初值为
空集(即图T中每一个顶点都构成一个连通分量)。
(2)将图G中的边按权值从小到大的顺序依次选取:
➊若选取的边未使生成树T形成回路,则加入TE;
❷否则舍弃,直到TE中包含(n-1)条边为止。
在这里插入图片描述
算法演示:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
。。。。。。。。
在这里插入图片描述
到第5号边时出现回路,则抛弃它,再判断第6号边
在这里插入图片描述
。。。。。。。。
在这里插入图片描述
从以上的流程我们可以知道:先将图中所有边按权值递增排序,T中包含所以顶点,然后依次选择最小边加入T中,每次加入时判断是否形成回路,若形成回路则从比它小一级的再开始遍历。

上述算法不是最优的。改进:堆排序、并查集
改进后Kruskal算法的时间复杂度为O(elog2e)。可以看出Kruskal算法执行时间与图中的边e有关,所以该算法适用于稀疏图求最小生成树。

最短路径

路径的概念:考虑带权有向图,把一条路径(仅仅考虑简单路径)上 所经边的权值之和定义为该路径的路径长度或称带权路径长度。
在这里插入图片描述
路径长度=c1+c2+…+cm
路径:(v,v1,v2,…,u)
从源点到终点可能不止一条路径,把路径长度最短的那条路径称为最短路径。

狄克斯特拉(Dijkstra)算法

该算法计算的是一个顶点到其余顶点的最短路径。

算法构造过程:
第1组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径v,… ,u,就将u加入到集合S中,直到全部顶点都加入到S中,算法就结束了)。
第2组为其余未求出最短路径的顶点集合(用U表示)。

在这里插入图片描述
算法演示:
在这里插入图片描述
首先将开始顶点放入S集合,其余顶点放在集合U中,dist[] 用于存储初始顶点0所有顶点最短权值,path[]用于存放顶点i到j的最短路径上顶点j的前一个顶点的编号。

我们通过流程图可以分析到:顶点0到顶点1的距离最短,所以将顶点1,放入集合S。然后将顶点1作为判断点,可以发现顶点1离顶点2最近,所以将顶点1,放入集合S,修改path中与顶点1有边的顶点2,4,将值修改为1;同理得到以下数据。

在这里插入图片描述
在这里插入图片描述
利用dist和path求最短路径长度和最短路径:
在这里插入图片描述
Dijkstra算法的时间复杂度为O(n²)。

弗洛伊德(Floyd)算法

该算法计算的是每对顶点之间的最短路径。

算法构造过程:
假设有向图G=(V, E)采用邻接矩阵存储。设置一个二维数组A用于存放当前顶点之间的最短路径长度,分量A[i][]表示当前顶点i中j的最短路径长度。
递推产生一个矩形序列:
A0,A1。。。An-1
Ak[i][j]:i到j的路径上所经过的顶点编号不大于k的最短路径长度。
在这里插入图片描述

  1. 0初始时,有AIilj]=g.edges[i][j]。
  2. 考虑从i到j的最短路径经过编号为k顶点的情况:
    在这里插入图片描述

算法遍历:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
。。。。。。。。
在这里插入图片描述
(1) 用二维数组A存储最短路径长度:
●Ak[i][j]表示考虑顶点0~k后得出的i到j的最短路径长度。
●An-1[i][j]表示最终的i到j的最短路径长度。

(2)用二维数组path存放最短路径:
●path k[i][j]表示考虑顶点0~k后得出的i到j的最短路径。
●path n-1[i][j]表示最终i到j的最短路径。
●path n-1[i][j]的值为j的前一个顶点。

从上述遍历我们可以看到:
初始时path-1就是该图邻接矩阵的表示,然后考虑顶点0,A0[i][j]表示最终的i到j经0的最短路径长度。经过比较没有任何路径上得到修改(即考虑顶点0时,不存在最短路径了)。
考虑顶点1,0到2由原来没有路径变成0-1-2,长度为9,所以A1[0][2]修改为9,path1[0][2]由-1修改为1
。。。
考虑顶点3,0-2由原来最短长度9,路径为0-1-2,但此时有一条更短的路径:0-3-2,长度为8。所以修改A3[0][2]为8,path3[0][2]由1改为3,依次推下去,得到所有结果

➊求最短路径长度:
由A3数组可以直接得到两个顶点之间的最短路径长度。
如A3[1][0]=6,说明顶点1到0的最短路径长度为6。
❷求最短路径:
求顶点1到0的最短路径:
path3[1][0]=2
path3[1][2]=3
path3[1][3]=1
顶点序列为0、2、3、1,则顶点1到0的最短路径为1-→3-→2-→0。
在这里插入图片描述
最后该算法的时间复杂度为O(n³)。

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值