挑战408——数据结构(27)——图的应用之最小生成树

图在我们现实生活中具有极其广泛的应用,我们这篇博文着重从以下几点展开分析:

  • 网络路由与路由选择Internet routers and traceroute
  • 拓扑排序Topological Sort
  • 最小生成树Minimum Spanning Trees
  • Kruskal’s 算法Kruskal’s algorithm
路由选择

实际上我们在学习网络的时候就已经接触过图。在《计算机网络》的网络层中,我们主要关注的是消息如何从您的计算机发送到Internet上的另一台计算机。我们通过ip数据报,从源地址出发到达目的地址。这个过程可能需要经过多个路由器,然后查看路由表进行存储转发。如果我们将其路由器抽象为一个节点,那么整个ip网络信息的传输实际上就可以看成是在一幅图中从节点A到节点B的遍历过程
在这里插入图片描述
假设上图F是一台服务器,一般的服务器都有自己的主机名和ip地址。现假设节点F的主要信息如下:

www.engineering.unsw.edu.au
IP address: 149.171.158.109

对于节点C,其路由表为:
在这里插入图片描述
我们知道,在RIP协议中,每个路由器都知道其邻居,并且具有其邻居表的副本。 因此,路由器B将具有以下表:
在这里插入图片描述
如果B要选择最短路径连接到F,它将选择哪个路由器?(显然下一跳应该选择路由器D)
在这里插入图片描述
在本地客户端,可以使用Tracert(liunx下为traceroute)命令来查看两个主机通信时候,经过的路由器。

最小生成树(MST)

我们在介绍图的过程当中,提到过一种图叫带权图。相对于其他的图而言,这种图的边上带有数字,表示这经过这条边时候的花费。这个很容易理解,也就是并不是路径最短就是最佳的方案。比如上图B到F。虽然B ->D->F的路径要短于B->C->D->F,但是前者不一定是最佳的选择方案,因为有可能B->D的耗时比B->C->D的耗时要长的的多!因此我们通常称这样的耗时为花费(cost),并且在边上注明,称为权!

问题的提出

如下图,假设这里有一系列的房屋,问如何铺设电线,可以使得连接所有房屋的电线的总成本最低?这是20世纪20年代早期研究最小生长树的最初动机。 (捷克数学家OtakarBorůvka完成的工作)。
在这里插入图片描述
MST算法的发展经历了下面几步骤:

  • Borůvka提出的原始MST算法(1926)现在称为Borůvka算法。
  • 后来,捷克数学家VojtěchJarník(1930)发明了一种现在称为Prim算法的算法。
  • 之后,美国数学家Joseph Kruskal(1956)开发了现在称为Kruskal算法的算法,这就是我们今天要呈现的算法。
最小生成树的定义

下面我们来给最小生成树下一个定义:
相连的无向加权图G的生成树(ST)是G的子图,它是树,并且连接(跨越)G的所有顶点。图G可以具有多个ST。 G的最小生成树(MST)是G的ST,其总权重在各个ST中最小。 图G可以具有多个MST,但是MST权重是唯一的。(Definition: A Spanning Tree (ST) of a connected undirected weighted graph G is a subgraph of G that is a tree and connects (spans) all vertices of G. A graph G can have multiple STs. A Minimum Spanning Tree (MST) of G is a ST of G that has the smallest total weight among the various STs. A graph G can have multiple MSTs but the MST weight is unique.

最小生成树(MST),解释起来就是:

  • 最小生成树,它是一棵树!
  • 它会遍历连接所有的节点
  • 这棵生成的树它不是唯一的(即可能不止一种路径),但是它的权的总和一定是最小的且唯一。

举个例子,比如你是电信局的人,负责在某一块区域铺设电缆,那么请找出铺设电话或有线电视系统电缆的最便宜方法。
在这里插入图片描述
右边的橙色部分就是一条最少花费的方式。从右往左看,他就是一棵树,且节点3就是树根。所以,寻找最小花费的路径的过程就是找出一棵最小生成树的过程。

Kruskal’s 算法

Kruskal’s algorithm,这是一种能在所给的图中找出最小生成树的算法。下面给出一段伪代码,看看具体的实现逻辑:

function kruskal(graph):
//从图中移除所有边
	Remove all edges from the graph.
	//将所有边放入优先级队列(基于它们自身的权重)
	Place all edges into a priority queue,based on their weight 
	//当优先级队列不为空时
	While the priority queue is not empty:
	//将边从优先级队列中取出
		Dequeue an edge e from the priority queue.
		//如果这条边添加上图中不会构成循环,则将此边添加到图中
		If e's endpoints doesn’t create a cycle ,add that edge into the graph.
		//否则,跳过该边
		Otherwise, skip the edge.

这个算法听起来似乎很简单:从图表中删除所有边。 反复找到造成循环的且花费最小的边并将其添加回来。 最终的结果就是整个图的MST.
来看下面的一幅带权图,我们试着用这种方法来找到该图的最小生成树。

  1. 首先我们先将图中的所有边删除,用虚线表示删除的边,pb是图中各边及其权数的优先级队列。
    在这里插入图片描述
  2. 根据算法,我们从优先级队列中取出队头 a:1.将它添加到图中,发现不构成环状,于是添加到图中(实线部分)
    在这里插入图片描述
  3. 接着我们继续将优先级队列中的其他元素添加到图中,接下来是b:2,结果符合要求,于是加到队列中:
    在这里插入图片描述
  4. 重复上述步骤。
  5. 当添加边到e:5时,我们发现此时构成了一个环状(红色部分),因此这条边不能加在图中,应该跳过这个边,继续添加接下来的边(如图):
    在这里插入图片描述
  6. 如此反复。当优先级中的队列为空时,表明我们已经将所有的边都遍历了一遍,此时生成的结果就是我们要找的MTS,如图:
    在这里插入图片描述

最终Kruskal’s 算法会按如下顺序输出所需的 MST:

{a, b, c, d, f, h, i, k, p}

而 MST的 总花费(权重)为:

1+2+3+4+6+8+9+11+16 = 60

在这里插入图片描述

实现思路
  1. 需要某种方式来识别哪些顶点“连接”到其他顶点,我们称这些顶点为“簇”

  2. 还需要一种有效的方法来找出给定顶点位于哪个群集中。

  3. 添加边缘时还需要合并群集。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值