《趣学算法》学习打卡Day 3


《趣学算法》学习打卡:Day3!

沟通无限校园网——最小生成树!

问题分析:

问题:把一个无向图连通,使得所需要的权值之和最小。

对于n个顶点的连通图(无向图),只需要n-1条边就可以使这个图连通,n-1条边要想保证图连通,就必须不包含回路,所以我们只要找出n-1条权值最小且无回路的边即可。

子图:从原图中选中一些顶点和边组成的图,称为原图的子图。

生成子图:选中一写边和所有顶点组成的图,称为原图的生成子图。

生成树:如果生成子图恰好是一棵树,则称为生成树。

最小生成树:权值之和最小的的生成树,则成为最小生成树。

最邻近值:这个点到其他点的众多边中,这条边最短(权值最小)

最邻近点:这个点到其他点的众多边中,权值最小的边的ID

算法设计:

把生成树的顶点放在一个集合U{1},把剩下的顶点看作一个集合V-U{2,3,4,5,6,7}。(是不是很像前面的“最短路径问题”)

首先,令U={u0},u0∈V,TE={}。u0可以是任何一个节点,因为最小生成树包含所有结点,所以从那个结点出发都可以得到最小生成树,不影响最终结果。TE为选中的边集。

贪心选择:选取连接U和V-U的所有最短边,既满足i∈U,j∈V-U,且边(i,j)是连接U和V-U的所有边中的最短边,即该边的权值最小。然后,将顶点j加入集合U,边(i,j)加入TE。继续上面的贪心选择一直进行到V-U的集合为空,此时,选取到的所有边恰好构成图G的一棵最小生成树T

最小生成树求解过程图:

U={1} ,V-U{2,3,4,5,6,7}

用一个数组closest[]记录当前点的最邻近点

-1表示没有

closest 1 2 3 4 5 6 7
-1 1 -1 -1 -1 1 1

无穷表示不通,权值无限大

用一个数组lowCost[]记录点的最邻近值

lowCost 1 2 3 4 5 6 7
23 28 36

显然我们就把2加入到集合U中

U={1,2},V-U={3,4,5,6,7}

从2出发,去更新新lowcost,如果lowcost更新了,就相应更新最邻近点closest

lowCost 1 2 3 4 5 6 7
23 ∞->20 28 36->1
closest 1 2 3 4 5 6 7
-1 1 -1->2 -1 -1 1 1->2

————重复以上步骤,直到V-U集合为空。

其实我是非常不愿意看伪代码的,但是理性告诉我看来有好处的,至少伪代码在以后的学习中还是有那么个地位在那

伪代码详解:

1、初始化。 重点是数据的表示方式 不要太在意用哪个来表示空,用哪个来表示无法连通

s[u0]=ture;//初始时,集合U中只有一个元素,即顶点u0
for(i=1;i<=n;i++)
{
    if(i!=u0)//除u0以外的顶点
    {
        lowcost[i]=c[u0][i];//u0到其它顶点的边值
        closest[i]=u0;//最临近点初始化为u0
        s[i]=falase;//初始化u0之外的顶点不属于集合U,即属于集合V-U
    }
    else
        lowcost[i]=0;
}

2、在集合V-U中寻找距离集合U最近的顶点t。

int temp=INF;//INF表示无穷大
int t=u0;
for(j=1;j<=n;j++)
{
    if((!s[j])&&(lowcost[j]

3、更新lowcost和closest数组。

s[t]=true;		//把t加入到集合u中;
for(j=1;j<=n;j++)//更新lowcost和closest
{
    //j在集合V-U中,且t到j的边值小于当前最邻近值
	if((!s[j])&&(c[t][j]

Day3总结:

? 这算是3天值任务最轻的一次了,知识点和逻辑关系在前两天的铺垫下,理解的更快了,但是笔记的做法自我感觉还是比较拉跨,不太像一个真正的笔记,跟多的是在聊天和对话,和自己对话,像在自己教自己一样,啰嗦!啰嗦的好处就是,自己对知识的理解就不在是停留在课本了,我能把一些思想用自己的话表述出来,这似乎很棒!

? 还有我觉得看书和做笔记是两回事,看书是读,笔记是理解,读书可以很快很快,把书中的文字浏览一遍不去字斟句酌,这样你每天的阅读激情都会很高,因为你在发现一个新事物。对于做笔记这个解,就是对事物的认知从敷衍的,浅薄的,进入更深层次的探讨,要去了解里面的实现机制,和表述机制。从笔记到代码实现又是另一种突破了。

我记得在哔哩哔哩上有位博主说:流水线的工作效率是最高的,所以我觉得我需要更该一下我自己的读书方式,先快速把书个翻一遍,再把书中的对知识点的讲述用自己的话来讲述一遍,再从头开始用代码来实现前面的例子。

所以我接下来的想法是:把第三章读完,就做粗略的笔记,快速挺进第四,第五章直到把书翻一边。然后转回来细读一遍做详细的笔记,最后再做一次代码实现。当然时间还是控制在30天以内。