能帮我看看嘛这个严重吗?我是7号来的例假,12号停,8天后又突然来大姨妈,这是我今天做的检查

本文始发于个人公众号:TechFlow原创鈈易,求个关注

今天是算法和数据结构专题的第19篇文章我们一起来看看最小生成树。

我们先不讲算法的原理也不讲一些七七八八的概念,因为对于初学者来说看到这些术语和概念往往会很头疼。头疼也是正常的因为无端突然出现这么多信息,都不知道它们是怎么来嘚也不知道这些信息有什么用,自然就会觉得头疼这也是很多人学习算法热情很高,但是最后又被劝退的原因

我们先不讲什么叫生荿树,怎么生成树有向图、无向图这些,先简单点从最基本的内容开始,完整地将这个算法梳理一遍

首先,我们先来看看最简单的數据结构——树

树是一个很抽象的数据结构,因为它在自然界当中能找到对应的物体我们在初学的时候,往往都会根据自然界中真实嘚树来理解这个概念所以在我们的认知当中,往往树是长这样的:

上面这张图就是自然界中树的抽象我们很容易理解。但是一般情况丅我们看到的树结构往往不是这样的,而是倒过来的也就是树根在上,树叶在下这样设计的原因很简单,没什么特别的道理只是洇为我们在遍历树的时候,往往从树根开始从树根往叶子节点出发。所以我们倒过来很容易理解一些我们把上面的树倒过来就成了这樣:

上面的两种画法当然都是正确的,但既然树可以正着放也可以倒过来放,我们自然也可以将它伸展开来放比如下面这张图,其实吔是一棵树只是我们把它画得不一样而已。

我们可以想象一下假如有一只无形的大手抓住了树根将它“拎起来”,那么它自然而然就變成了上面的样子

然后你会发现,如果真的有这样大手它不管拎起哪个节点,都会得到一棵树也就是说,如果树根的位置对我们不洅重要的话树其实就等价于上面这样的图。

那么这样的图究竟是什么图呢它有什么性质呢?所有的图都能看成是树吗

显然这三种情況都不是树,第一种是因为图中的边有方向了有了方向之后,图中连通的情况就被破坏了在我们认知当中树应该是全连通的,就好像洎然界中的一只蚂蚁可以走到树上任何位置。不能全连通自然就不是树。情况2也不对因为有了环,树是不应该有环的自然界中的樹是没有环的,不存在某根树枝自己绕一圈同样,我们逻辑中的树也是没有环的否则我们递归访问永远也找不到终点。第三种情况也┅样有些点孤立在外,不能连通自然也不是树。

那我们总结一下就可以回答这个问题。树是什么树就是可以全连通(无向图),並且没有环路的图

从刚才的分析当中,我们得到了一个很重要的结论树的本质就是图,只不过是满足了一些特殊性质的图这也是为什么树的很多算法都会被收纳进图论这个大概念当中。

全连通和没有环路这两个性质出发我们又可以得到一个很重要的结论,对于一棵拥有n个节点的树而言它的边数是固定的,一定是n-1条边如果超过n-1条边,那么当中一定存在环路如果小于n-1条边,那么一定存在不连通嘚部分但注意,它只是一个必要条件不是一个充分条件。也就是说并不是n个点n-1条边就一定是树这很容易构造出反例。

这个结论虽然佷简单但是很有用处,它可以解决一个由图转化成树的问题

也就是说当下我们拥有一个复杂图,我们想要根据这个图生成能够连通所囿节点的树这个时候应该怎么办?如果我们没有上面的性质会有一点无从下手的感觉。但有了这个性质之后就明确多了。我们一共囿两种办法第一种办法是删减边,既然是一个复杂图说明边的数量一定超过n-1。那么我们可以试着删去一些边最后留下一棵树。第二種做法与之相反是增加边。也就是说我们一开始把所有的边全部撤掉然后一条一条地往当中添加n-1条边,让它变成一棵树

我们试着想┅下,会发现删减边的做法明显弱于添加边的方法原因很简单,因为我们每一次在删除边的时候都面临是否会破坏树上连通关系的拷问比如下图:

如果我们一旦删去了AB这条边,那么一定会破坏整个结构的连通性我们要判断连通关系,最好的办法就是我们先删除这条边然后试着从A点出发,看看能否到达B点如果可以,那么则认为这条边可以删除如果图很大的话,每一次删除都需要遍历整张图这会帶来巨大的开销。并且每一次删除都会改变图的结构很难缓存这些结果。

因此删除边的方式并不是不可行,只是复杂度非常高正因此,目前比较流行的两种最小生成树的算法都是利用的第二种也就是添加边的方式实现的。

到这里我们就知道了,所谓的最小生成树算法就是从图当中挑选出n-1条边将它转化成一棵树的算法。

我们先不考虑边上带权重的情况我们假设所有边都是等价的,先来看看生成問题怎么解决再来进行优化求最小。

如果采用添加边的方法面临的问题和上面类似,当我们选择一条边的时候我们如何判断这条边昰有必要添加的呢?这个问题需要用到树的另外一个性质

由于没有环路,树上任意两点之间的路径有且只有一条。因为如果存在两点の间的路径有两条那么必然可以找到一个环路。它的证明很简单但是我们很难凭自己想到这个结论。有了这个结论就可以回答上面嘚那个问题,什么样的边是有必要添加的也就是两个点之间不存在通路的时候。如果两个点之间已经存在通路那么当前这条边就不能添加了,否则必然会出现环如果没有通路,那么可以添加

所以我们要做的就是设计一个算法,可以维护树上点的连通性

但是这又带來了一个新的问题,在树结构当中连通性是可以传递的。两个点之间连了一条边并不仅仅是这两个点连通,而是所有与这两个点之间連通的点都连通了比如下图:

这张图当中A和B连了一条边,这不仅仅是A和B连通而是左半边的集合和右半边集合的连通。所以虽然A只是囷B连通了,但是和C也连通了AC这条边也一样不能被加入了。也就是说A和B连通其实是A所在的集合和B所在的集合合并的过程。看到集合的合並有没有一点熟悉的感觉?对嘛上一篇文章当中我们讲的并查集算法就是用来解决集合合并和查询问题的。那么显然可以用并查集來维护图中这些点集的连通性。

如果对并查集算法有些遗忘的话可以点击下方的传送门回顾一下:

利用并查集算法,问题就很简单了┅开始所有点之间都不连通,那么所有点单独是一个集合如果当前边连通的两个点所属于同一个集合,那么说明它们之间已经有通路了这条边不能被添加。否则的话说明它们不连通,那么将这条边连上并且合并这两个集合。

于是我们就解决了生成树这个问题。

接丅来我们为图中的每条边加上权重,希望最后得到的树的所有权重之和最小

比如,我们有下面这张图我们希望生成的树上所有边的權重和最小

观察一下这张图上的边长短不一。根据贪心算法我们显然希望用尽量短的边来连通树。所以Kruskal算法的原理非常简单粗暴僦是对这些边进行长短排序,依次从短到长遍历这些边然后通过并查集来维护边是否能够被添加,直到所有边都遍历结束

可以肯定,這样生成出来的树一定是正确的虽然我们对边进行了排序,但是每条边依然都有可能会被用上排序并不会影响算法的可行性。但问题昰这样贪心出来的结果一定是最优的吗?

这里我们还是使用之前讲过的等价判断方法。我们假设存在两条长度一样的边那么我们的決策是否会影响最后的结果呢?

两个完全相等的边一共只有可能出现三种情况为了简化图示,我们把一个集合看成是一个点第一种情況是这两条边连通四个不同的集合:

那么显然这两条边之间并不会引起冲突,所以我们可以都保留所以这不会引起反例。

第二种情况是這两条边连通三个不同的集合:

这种情况和上面一样我们可以都要,并不会影响连通情况所以也不会引起反例。

最后一种是这两条边連通的是两个集合也就是下面这样。

在这种情况下这两条件之间互相冲突,我们只能选择其中的一条但是显然,不论我们怎么选都昰一样的因为都是连接了这两个连通块,然后带来的价值也是一样的并不会影响最终的结果

当我们把所有情况列举出来之后我们僦可以明确,在这个问题当中贪心法是可行的并不会引起反例,所以我们可以放心大胆地用

明白了算法原理之后,我们来看看这个算法的实际问题其实这个算法在现实当中的使用蛮多的,比如自来水公司要用水管连通所有的小区而水管是有成本的,那么显然自来水公司希望水管的总长度尽量短比如山里的村庄通电,要用尽量少的电缆将所有村庄连通这些类似的问题其实都可以抽象成最小生成树來解决。当然现实中的问题可能没有这么简单除了考虑成本和连通之外,还需要考虑地形、人文、社会等其他很多因素

最后,我们试著用代码来实现一下这个算法

其实主要都是利用并查集,我们额外写的代码就只有几行而已是不是非常简单呢?

相信大家也都感觉到叻Kruskal算法的原理非常简单如果你是顺着文章脉络这样读下来,相信一定会有一种顺水推舟一切都自然而然的感觉。也正是因此它非常苻合直觉,也非常容易理解一旦记住了就不容易忘记,即使忘记了我们也很容易自己推导出来这并不是笑话,有一次我在比赛的时候臨时遇到了当时许久不写Kruskal算法,一时想不起来凭着仅有的一点印象,硬是在草稿纸上推导了一遍算法

在下一篇文章当中我们继续研究最小生成树问题,一起来看另外一个类似但不相同的算法——Prim

今天的文章就到这里,原创不易需要你的一个关注,关注我获取更多攵章

}
  • 优质卵泡有可能已经排掉了优質卵泡排掉后还会有小卵泡的,就是小的卵泡慢慢就会萎缩一般子宫内膜在两毫米到10毫米之间,月经来临时子宫内膜在10毫米左右,如果月经來临以后,子宫内膜会变薄。可以检查一下内膜变薄的原因

}

我要回帖

更多关于 帮我看看嘛 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信