6.8.最小生成树


一.复习:

1.生成树:

对于一个连通的无向图,假设图中有n个顶点,如果能找到一个符合以下要求的子图:

子图中包含图中所有的顶点,同时各个顶点保持连通,

而且子图的边的数量只有n-1条,

那么这样的子图就是生成树,一个连通图可能有多个生成树。

2.广度优先生成树:

3.深度优先生成树:


二.最小生成树(最小代价树):生成树必须包含图中所有的顶点

1.前言:

假设有一个城市叫P城,P城周围规划了学校、农场、电站、渔村、矿场,

各个地方之间有上图所示的修路方案,其中数字表示修路的成本,比如修一条P城和学校之间的路需要1块钱,修一条学校和矿场之间的路需要5块钱,

现在为了节省P城的财政支出,没有必要把所有的可行的道路都修一遍,

因此需要制定一个修路方案,这个方案要求所有地方都是连通的即各个地方之间是相互可到达的(各个地方之间不一定是相邻的),但是成本又必须降到最低,此时有如下两种方案:

左边的方案可以使得各个地方连通,代价是20块钱(图片打错了);

右边的方案也可以使各个地方连通,但代价是16块钱,

但是否有更便宜的方案呢?这就是最小生成树(最小代价树)要研究的问题。

对于带权的连通图,它可以有多个生成树,我们要从所有的生成树当中找出各个边的权值之和最小即代价最小的那棵树,这个树就是最小生成树。

2.概念:

注:最小生成树研究的是带权的连通无向图。

3.特例:当带权连通的无向图的权值都为一个数

以上述图片的带权连通无向图为例,可得出如下两个生成树:

由生成树的概念可知这两棵生成树的边都是5条(边等于顶点总数减一,此时有6个顶点),由于每一条边的权值都为1,因此这两棵生成树所有边的权值之和都为5,

由此可知本例中带权无向图的任意一棵生成树的所有边的权值之和都为5,因此最小的权值之和为5,

结论:假设一个带权连通无向图的顶点数为V个,边为E条,边的权值都为a,

该图的所有生成树都只有(V-1)条边,其权值之和为(V-1) * a,由此可知最小生成树的权值之和为(V-1) * a,因为所有树都一样。

4.性质:

  • 如果一个连通图本身就是一棵树(树不存在环路),也就是图中各个顶点连通但不存在环,那么这个图的最小生成树就是它本身->因为如果连通图是树时,那么它已经是生成树了,而且无法再有更小的生成树了,再有的话就会缺顶点,不符合生成树的条件,所以此时这个图的最小生成树就是它本身

  • 只有连通图才有生成树

  • 对于非连通图,只会有生成森林,因为非连通图不止一个连通分量,生成的也就不止一个生成树,最终就是生成森林(这里生成必须要包括图中的所有顶点,不然不符合生成的条件)

5.总结:


三.求最小生成树-Prim算法(普里姆算法):

1.例一:

以上述图片为例,挑选图中任意一个顶点,从该顶点出发构建生成树:

如上图,比如从P城这个顶点出发构建生成树,之后每次将代价最小的新顶点纳入生成树,直到所有顶点都纳入为止,

此时要构建的生成树中只有P城这一个顶点,从P城出发,分别对比到达学校、矿场、渔村、电站、农场所需要的代价,可知从P城到达学校的代价最小,因此接下来要把学校这个顶点纳入生成树,如下图:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中有P城和学校两个顶点,

现在要从P城或学校出发,在农场、电站、渔村、矿场中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为4,如下图:

意味着可以把矿场或者渔村纳入生成树中,

此时先把矿场纳入生成树,如下图:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中包括P城、学校和矿场,

现在要从P城或学校或矿场出发,在农场、电站、渔村中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为2,如下图:

意味着把渔村纳入生成树中,如下图:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中包括P城、学校、矿场和渔村,

现在要从P城或学校或矿场或渔村出发,在农场、电站中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为5,如下图:

意味着把农场纳入生成树中,如下图:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中包括P城、学校、矿场、渔村和农场,

现在要从P城或学校或矿场或渔村或农场出发,在电站中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为3,如下图:

意味着把电站纳入生成树中,如下图:

如下图,最终得到了最小生成树:

也就是说按照如上图所得出的最小生成树进行施工的话,只需要付15块钱,也是最小代价。

2.例二:

以上述图片为例,挑选图中任意一个顶点,从该顶点出发构建生成树:

如上图,比如从P城这个顶点出发构建生成树,之后每次将代价最小的新顶点纳入生成树,直到所有顶点都纳入为止,

此时要构建的生成树中只有P城这一个顶点,从P城出发,分别对比到达学校、矿场、渔村、电站、农场所需要的代价,可知从P城到达学校的代价最小,因此接下来要把学校这个顶点纳入生成树,如下图:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中有P城和学校两个顶点,

现在要从P城或学校出发,在农场、电站、渔村、矿场中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为4,如下图:

意味着可以把矿场或者渔村纳入生成树中,

此时把渔村纳入生成树,如下图:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中包括P城、学校、渔村,

现在要从P城或学校或渔村出发,在农场、电站、矿场中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为2,如下图:

意味着把矿场纳入生成树中,如下图:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中包括P城、学校、渔村、矿场,

现在要从P城或学校或渔村或矿场出发,在农场、电站中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为5,如下图:

意味着把农场纳入生成树中,如下图:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中包括P城、学校、渔村、矿场、农场,

现在要从P城或学校或渔村或矿场或农场出发,在电站中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为3,如下图:

意味着把电站纳入生成树中,如下图:

如下图,最终得到了最小生成树:

也就是说按照如上图所得出的最小生成树进行施工的话,只需要付15块钱,也是最小代价。

3.对比例一与例二分别得出的最小生成树:

以上两棵生成树的最小代价都是15,

因此同一个图可能有多个最小生成树,虽然形态不同,但是这些最小生成树的所有边的权值之和都是一样且最小的。

4.例三:

以上述图片为例,挑选图中任意一个顶点,从该顶点出发构建生成树:

如上图,比如从农场这个顶点出发构建生成树,之后每次将代价最小的新顶点纳入生成树,直到所有顶点都纳入为止,

此时要构建的生成树中只有农场这一个顶点,从农场出发,分别对比到达学校、电站、渔村、矿场、P城所需要的代价,可知从农场到达电站的代价最小,因此接下来要把电站这个顶点纳入生成树,如下图:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中有农场和电站两个顶点,

现在要从农场或电站出发,在渔村、矿场、学校、P城中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为5,如下图,因此要把P城纳入生成树中:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中有农场、电站、P城,

现在要从农场或电站或P城出发,在渔村、矿场、学校中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为1,如下图,因此要把学校纳入生成树中:

如上图,在当前生成树下重复刚才的步骤,此时的生成树中有农场、电站、P城、学校,

现在要从农场或电站或P城或学校出发,在渔村、矿场中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为4,如下图,因此可以把矿场或渔村纳入生成树中,此时把矿场纳入生成树中(这里把渔村纳入生成树后得出的最小生成树的最小代价一致):

如上图,在当前生成树下重复刚才的步骤,此时的生成树中有农场、电站、P城、学校、矿场,

现在要从农场或电站或P城或学校或矿场出发,在渔村中选择一个代价最小的顶点连到当前生成树中,

由上图可知最小的代价为2,如下图,因此可以把渔村纳入生成树中:

最终得出了如上图所示的最小生成树,最小代价也是15,与例一、例二的最小代价一样。


四.求最小生成树-Kruskal算法(克鲁斯卡尔):

实例:

执行过程:每次选择一条权值最小的边,使这条边的两头连通(原本已经连通的就不选),直到所有顶点连通。

以上述图片为例,一开始图里的各个顶点都独立存在,各个顶点之间不存在边,所以用虚线标注,

现在从所有的虚线里挑出权值最小的一条,显然权值最小的是1这条虚线,如下图:

如上图,1这条虚线的两头是P城和学校这两个顶点,这两个顶点此时还没有连通,所以把这条虚线选中,使这两个顶点连通,如下图:

如上图,继续从所有的虚线里挑出权值最小的一条,显然权值最小的是2这条虚线,如下图:

如上图,2这条虚线的两头是渔村和矿场这两个顶点,这两个顶点此时还没有连通,所以把这条虚线选中,使这两个顶点连通,如下图:

如上图,继续从所有的虚线里挑出权值最小的一条,显然权值最小的是3这条虚线,如下图:

如上图,3这条虚线的两头是农场和电站这两个顶点,这两个顶点此时还没有连通,所以把这条虚线选中,使这两个顶点连通,如下图:

如上图,继续从所有的虚线里挑出权值最小的一条,显然权值最小的是4这条虚线,如下图:

如上图,P城和矿场之间的虚线的权值、P城和渔村之间的虚线的权值都为4,现在选择P城和矿场之间的虚线,P城和矿场这两个顶点此时还没有连通,所以把这条虚线选中(P城和渔村这两个顶点此时也没有连通,所以选这条虚线也可以),使这两个顶点连通,最终P城、矿场、渔村、学校这几个顶点就都连通了,如下图:

如上图,继续从所有的虚线里挑出权值最小的一条,显然权值最小的是4这条虚线,如下图:

如上图,此时权值为4的这条虚线的两头是P城和渔村,由于P城和渔村这两个顶点已经连通了,所以这条虚线需要跳过不选,如下图:

如上图,继续从所有的虚线里挑出权值最小的一条,显然权值最小的是5这条虚线,如下图:

如上图,P城和农场之间的虚线的权值、学校和矿场之间的虚线的权值都为5,由于学校和矿场已经连通,因此学校和矿场之间的虚线不选,而P城和农场之间还没有连通,所以应选中P城和农场之间的虚线,如下图:

如上图,至此,所有的顶点全部连通,Kruskal算法(克鲁斯卡尔)结束。

如下图,本例采用Kruskal算法(克鲁斯卡尔)得出的最小生成树的最小代价为15,与用Prim算法(普里姆算法)得出的结果一致:


五.Prim算法(普里姆算法) v.s. Kruskal算法(克鲁斯卡尔):

假设图中有V个顶点、E条边:

对于Prim算法(普里姆算法),每一次是选择一个顶点开始;

对于Kruskal算法(克鲁斯卡尔),每一次是选择一条边开始;

因此这两个算法所表现出的时间复杂度也就不一样,

Prim算法(普里姆算法)的时间复杂度只与顶点的个数有关,适用于边稠密图即边多的图(因为边多的话顶点相对少一些),

Kruskal算法(克鲁斯卡尔)的时间复杂度只与边的个数有关,适用于边稀疏图即边少的图(因为边越少越能在短时间完成)。


六.Prim算法的实现思想:

1.实例:

以上述图片为例,假设从v0顶点开始,设置isJoin数组和lowCost数组:

isJoin数组用于记录图中的顶点是否被加入正在组建的生成树中,由于刚开始v0已经在生成树中,所以v0在isJoin数组的值为true(上述图片标记为勾),其余的顶点没有加入生成树中,因此其余的顶点对应的值都为false(上述图片标记为叉);

lowCost数组用于记录把这些顶点加入到已经组建的生成树里所需要花费的最低代价->最开始选中了v0,

由于v0与v0之间不存在边,所以v0对应的lowCost数组的值为0,

由于v0与v1之间有一条边,这条边的权值为6,因此把v1加入到组建的生成树中所需要付出的最低代价是6,所以v1对应的lowCost数组的值为6,

由于v0与v2之间有一条边,这条边的权值为5,因此把v3加入到组建的生成树中所需要付出的最低代价是5,所以v2对应的lowCost数组的值为5,

由于v0与v3之间有一条边,这条边的权值为1,因此把v2加入到组建的生成树中所需要付出的最低代价是1,所以v3对应的lowCost数组的值为1,

而v4与v5这两个顶点和v0之间都没有直接相连的边,所以就目前来看,暂时无法把v4、v5放到组建好的生成树中,因此v4与v5对应的lowCost的值都用无穷记录,也可以用别的记录。

如下图,开始进行第一轮处理:

首先需要检查isJoin数组和lowCost数组,最终找出一个还没有被加入生成树且代价最低的顶点,

由上述图片可知,v3顶点没有加入生成树中且代价最小,因此把v3顶点加入生成树中,如下图:

如上图,要把v3顶点在isJoin数组中对应的值修改为true即勾,表示已加入生成树中,继续如下图:

如上图,需要循环遍历lowCost数组,更新还没加入的各个顶点对应的lowCost值,

现在加入了v3这个顶点之后,对于其他的还没有被加入生成树的顶点,接下来加入生成树的代价有可能会改变,

因为生成树中相较于一开始多了个v3顶点,最开始只有v0顶点时加入v1顶点最低代价为6,现在多了个v3顶点,加入v1顶点的最低代价为5,显然小于6,因此接下来如果要把v1加到生成树中,所需要付出的最低代价就从6变成了5,

因此把v1对应的lowCost值修改为5,同理现在

加入v2的最低代价为4,因此把v2对应的lowCost值修改为4,

加入v4的最小代价为6,因此把v4对应的lowCost值修改为6,

加入v5的最小代价为4,因此把v5对应的lowCost值修改为4,

由于v0与v3这两个顶点已经加入到生成树中,所以对应的lowCost值无需修改(因为之后不会再加入v0与v3这两个顶点),

最终lowCost数组中的值依次为0、5、4、1、6、4,

如下图:

如下图,开始进行第二轮处理:原理与第一轮一样

首先需要检查isJoin数组和lowCost数组,最终找出一个还没有被加入生成树且代价最低的顶点,

由上述图片可知,v2顶点和v5顶点都没有加入生成树中且代价都是最小的(代价都为4),因此v2顶点和v5顶点都可以加入生成树中,但如果是从头到尾去扫描lowCost数组中的元素,v2顶点是第一个被挑选并加入生成树中的,如下图:

如上图,要把v2顶点在isJoin数组中对应的值修改为true即勾,表示已加入生成树中,继续如下图:

如上图,需要循环遍历lowCost数组,更新还没加入的各个顶点对应的lowCost值,

由上述图片可知,加入v2顶点之后,

加入v1的最低代价为5,无需修改,

加入v4的最小代价为6,无需修改,

加入v5的最小代价为2,因此把v5对应的lowCost值修改为2,

由于v0、v3和v2这三个顶点已经加入到生成树中,所以对应的lowCost值无需修改(因为之后不会再加入v0、v3和v2这三个顶点),

最终lowCost数组中的值依次为0、5、4、1、6、2,

如下图:

如下图,开始进行第三轮处理:

首先需要检查isJoin数组和lowCost数组,最终找出一个还没有被加入生成树且代价最低的顶点,

由上述图片可知,v5顶点没有加入生成树中且代价最小,因此把v5顶点加入生成树中,如下图:

如上图,要把v5顶点在isJoin数组中对应的值修改为true即勾,表示已加入生成树中,继续如下图:

如上图,需要循环遍历lowCost数组,更新还没加入的各个顶点对应的lowCost值,

由上述图片可知,加入v5顶点之后,

加入v1的最低代价为5,无需修改,

加入v4的最小代价为6,无需修改,

由于v0、v3、v2和v5这四个顶点已经加入到生成树中,所以对应的lowCost值无需修改(因为之后不会再加入v0、v3、v2和v5这四个顶点),

最终lowCost数组中的值依次为0、5、4、1、6、2,

如下图:

如下图,开始进行第四轮处理:

首先需要检查isJoin数组和lowCost数组,最终找出一个还没有被加入生成树且代价最低的顶点,

由上述图片可知,v1顶点没有加入生成树中且代价最小,因此把v1顶点加入生成树中,如下图:

如上图,要把v1顶点在isJoin数组中对应的值修改为true即勾,表示已加入生成树中,继续如下图:

如上图,需要循环遍历lowCost数组,更新还没加入的各个顶点对应的lowCost值,

由上述图片可知,加入v1顶点之后,

加入v4的最小代价为3,因此把v4对应的lowCost值修改为2,

由于v0、v3、v2、v5和v1这五个顶点已经加入到生成树中,所以对应的lowCost值无需修改(因为之后不会再加入v0、v3、v2、v5和v1这五个顶点),

最终lowCost数组中的值依次为0、5、4、1、3、2,

如下图,开始进行第五轮处理:

首先需要检查isJoin数组和lowCost数组,最终找出一个还没有被加入生成树且代价最低的顶点,

由上述图片可知,v4顶点没有加入生成树中且代价最小,因此把v4顶点加入生成树中,如下图:

如上图,要把v4顶点在isJoin数组中对应的值修改为true即勾,表示已加入生成树中,

最终所有顶点全部加入到生成树中,Prim算法结束。

2.时间复杂度分析:

上述例子中进行了好几轮的处理最终得出最小生成树,从代码角度来看就是好几轮的循环,

由于每一轮的循环都会选择一个新的顶点把它放入生成树中,假设图中有n个顶点就需要n-1轮的循环,因为第一个顶点不需要循环,

而每一轮的处理当中又需要进行两次循环遍历,第一次循环遍历所有的顶点来从isJoin数组和lowCost数组中找出未加入生成树且代价最小的顶点,第二次循环遍历所有的顶点来更新lowCost数组,所以每一轮的时间复杂度为O(2n),等价于O(n),

由于需要n-1轮循环,所以总的时间复杂度就是O( n * (n-1) ),等价于O( n * n - n ),等价于O( n * n ),

如果改为图中有V个顶点,时间复杂度就是O( |V| * |V|)。


七.Kruskal算法(克鲁斯卡尔)的实现思想:

1.实例:

如下图,由于Kruskal算法(克鲁斯卡尔)每次要选择一条权值最小的边,所以要先把各条边按照权值递增的次序进行排序:

如上图,权值最小的边是权值为1的这条边,两边的顶点是v0和v3,所以上述图片里的第一行数据中weight为1、Vertex1为v0、Vertex2为v3,该算法的执行过程就是把所有的边都检查一遍。

如上图,第一条边的权值为1,两边连的顶点是v0和v3,接下来就要检查v0和v3是否连通,进行这个判断用到了并查集(详情见"5.15.并查集"),大致的思想就是刚开始要把所有的顶点分别看作是不同的集合,所以对于第一条边的两个顶点v0和v3,他们刚开始从属于不同集合,也就意味着他们此时不连通,因此就可以把这条边选中,如下图:

此时v0和v3这两个顶点就属于同一个集合了,

如下图,接下来进行第二轮的处理,权值为2的边的两头为v2和v5,v2和v5此时不属于同一个集合即v2和v5不连通,所以把v2和v5连起来,把v2和v5归并为同一个集合:

如下图,接下来进行第三轮的处理,权值为3的边的两头为v1和v4,v1和v4此时不属于同一个集合即v1和v4不连通,所以把v1和v4连起来,把v1和v4归并为同一个集合:

如下图,接下来进行第四轮的处理,其中一条权值为4的边的两头为v2和v3,v2和v3此时不属于同一个集合即v2和v3不连通,所以把v2和v3连起来,把v2和v3归并为同一个集合:

如下图,接下来进行第五轮的处理,其中一条权值为4的边的两头为v3和v5,v3和v5此时属于同一个集合即v3和v5连通,所以v3和v5之间的边会跳过,不选中:

接下来的过程同理,最终把v1与v3连接后就得出最小生成树,

如下图,总之就是要把所有的边都遍历一遍,每当处理一条边时,需要判断这条边所连接的两个顶点是否从属于同一个集合,如果不是,那就把这条边选中,如果是,就不选中:

2.时间复杂度分析:

假设图中共有e条边:

每轮循环中判断两个顶点是否属于同一个集合,要用到并查集,这个过程的时间复杂度详情见"5.15.并查集",共e轮。


八.总结:


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/901939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot 集成金蝶 API 演示

✨ Spring Boot 集成金蝶 API 演示:登录 / 注销 Cookie 保存 本文将通过 Spring Boot 完整实现一套金蝶接口集成模型,包括: ✅ 普通登录✅ AppSecret 登录✅ 注销✅ Cookie 保存与复用 📅 项目结构 src/ ├── controller/ │…

React 受控表单绑定基础

React 中最常见的几个需求是: 渲染一组列表绑定点击事件表单数据与组件状态之间的绑定 受控表单绑定是理解表单交互的关键之一。 📍什么是受控组件? 在 React 中,所谓“受控组件”,指的是表单元素(如 &l…

基于FPGA的AES加解密系统verilog实现,包含testbench和开发板硬件测试

目录 1.课题概述 2.系统测试效果 3.核心程序与模型 4.系统原理简介 4.1 字节替换(SubBytes) 4.2 行移位(ShiftRows) 4.3 列混合(MixColumns) 4.4 轮密钥加(AddRoundKey) 4.…

6.5 GitHub监控系统实战:双通道采集+动态调度打造高效运维体系

GitHub Sentinel Agent 定期更新功能设计与实现 关键词:GitHub API 集成、定时任务调度、Python 爬虫开发、SMTP 邮件通知、系统稳定性保障 1. GitHub 项目数据获取功能 1.1 双通道数据采集架构设计 #mermaid-svg-ZHJIMXcMAyDHVhmV {font-family:"trebuchet ms",v…

Explorer++:轻量级高效文件管理器!!

项目简介 Explorer 是一款专为Windows操作系统设计的轻量级且高效的文件管理器。作为Windows资源管理器的强大替代方案,它提供了丰富的特性和优化的用户体验,使得文件管理和组织变得更加便捷高效。无论是专业用户还是普通用户,都能从中受益&a…

7、生命周期:魔法的呼吸节奏——React 19 新版钩子

一、魔法呼吸的本质 "每个组件都是活体魔法生物,呼吸节奏贯穿其生命始终,"邓布利多的冥想盆中浮现三维相位图,"React 19的呼吸式钩子,让组件能量流转如尼可勒梅的炼金术!" ——以霍格沃茨魔法生理…

理解计算篇--正则表达式转NFA--理论部分

空正则表达式转NFA单字符正则表达式转NFA拼接正则表达式转NFA选择正则表达式转NFA重复正则表达式转NFA 正则表达式转NFA–实战部分 空正则表达式转NFA 转换步骤: 构建1个只有1个状态的NFA起始状态也是接受状态没有规则,即规则集为空 单字符正则表达式…

稳态模型下的异步电机调速【运动控制系统】

异步电动机: n1是同步转速(电机和磁芯同步时候的转速) n:电机的实际转速 异步电动机恒压频比的概念,为什么基频以下可以采取恒压频率,基频以上不可以采用恒压频比: 异步电动机的恒压频比&…

【KWDB 创作者计划】_算法篇---Stockwell变换

文章目录 前言一、Stockwell变换原理详解1.1 连续S变换定义1.2 离散S变换1.3简介 二、S变换的核心特点2.1频率自适应的时频分辨率2.1.1高频区域2.1.2低频区域 2.2无交叉项干扰2.3完全可逆2.4相位保持2.5与傅里叶谱的直接关系 三、应用领域3.1地震信号分析3.2生物医学信号处理3.…

云计算(Cloud Computing)概述——从AWS开始

李升伟 编译 无需正式介绍亚马逊网络服务(Amazon Web Services,简称AWS)。作为行业领先的云服务提供商,AWS为全球开发者提供了超过170项随时可用的服务。 例如,Adobe能够独立于IT团队开发和更新软件。通过AWS的服务&…

Python爬虫第17节-动态渲染页面抓取之Selenium使用下篇

目录 引言 一、获取节点信息 1.1 获取属性 1.2 获取文本值 1.3 获取ID、位置、标签名、大小 二、切换Frame 三、延时等待 3.1 隐式等待 3.2 显式等待 四、前进后退 五、Cookies 六、选项卡管理 七、异常处理 引言 这一节我们继续讲解Selenium的使用下篇&#xff0…

容器docker入门学习

这里写目录标题 容器容器的软件厂商 dockerdocker引擎 虚拟化虚拟化技术 docker安装详解1、安装检查2、安装yum相关的工具3、安装docker-ce软件4、查看docker版本5、启动docker服务6、设置docker开机启动7、查看有哪些docker容器运行进程8、查看容器里有哪些镜像9、下载nginx软…

文献总结:NIPS2023——车路协同自动驾驶感知中的时间对齐(FFNet)

FFNet 一、文献基本信息二、背景介绍三、相关研究1. 以自车为中心的3D目标检测2. 车路协同3D目标检测3. 特征流 四、FFNet网络架构1. 车路协同3D目标检测任务定义2. 特征流网络2.1 特征流生成2.2 压缩、传输与解压缩2.3 车辆传感器数据与基础设施特征流融合 3. 特征流网络训练流…

git 出现 port 443 Connection timed out

梯子正常延迟不算严重,但在使用git push时反复出现 fatal: unable to access https://github.com/irvingwu5/xxxx.git/ Error in the HTTP2 framing layer Failed to connect to github.com port 443 after 136353 ms: Connection timed out 将git的网络配置与梯子…

【2025年4月18日】android studiio最新设置沉浸式状态栏教程

😫【2025年4月18日】搞了一整天,终于完美搞定 Android 沉浸式状态栏(WebView 本地HTML) 最近在做一个个人项目,用 Android 加载本地 HTML 做个小工具。按理说用 WebView 加载页面很简单嘛——结果沉浸式状态栏这个坑…

如何删除 Launchpad 中 Chrome 的图标

有一天突然在 Launchpad 中出现下面的图标,在 Finder 的 Applications 中也没有,不知道如何删除。最终在《How to remove chrome app icons from launchpad?》中找到了答案。中文互联网上并没有搜到相关帖子,遂作记录。 解决办法很简单&am…

PHP8.2.9NTS版本使用composer报错,扩展找不到的问题处理

使用composer install时报错: The openssl extension is required for SSL/TLS protection but is not available. If you can not enable the openssl extension, you can disable this error, at y our own risk, by setting the ‘disable-tls’ option to true.…

一本通 2063:【例1.4】牛吃牧草 1005:地球人口承载力估计

Topic: Ideas: 为什么把这两道题放在一起呢?就是因为这两道题很类似,都是很简单的数学题,只要你会列出数学等式,你就学会这道题了! 下面把计算过程展示给大家 Code: //2025/04/18…

基于用户的协同过滤推荐系统实战项目

文章目录 基于用户的协同过滤推荐系统实战项目1. 推荐系统基础理论1.1 协同过滤概述1.2 基于用户的协同过滤原理1.3 相似度计算方法1.3.1 余弦相似度(Cosine Similarity)1.3.2 皮尔逊相关系数(Pearson Correlation)1.3.3 欧几里得距离(Euclidean Distance)1.3.4 调整余弦相似度…