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轮。
八.总结:

相关文章:
6.8.最小生成树
一.复习: 1.生成树: 对于一个连通的无向图,假设图中有n个顶点,如果能找到一个符合以下要求的子图: 子图中包含图中所有的顶点,同时各个顶点保持连通, 而且子图的边的数量只有n-1条࿰…...
QT中栅格模式探索
1、Qt中选择了栅格模式,如下图所示: 2、在进行整个大的UI界面布局时,需了解每个控件所需要选择的属性sizePolicy。 sizePolicy包含如下几种选择: 3、举个例子:此时整个UI界面,我采用了栅格模式…...
SLAM | 激光SLAM中的退化问题
在激光SLAM中,判断退化环境的核心是通过数学建模分析环境特征对位姿估计的约束能力。除了LOAM中提出的退化因子D外,还存在多种基于表达式和阈值设定的方法。以下是几种典型方法及其实现原理: 1. 协方差矩阵特征值分析 原理:通过分析点云协方差矩阵的特征值分布,判断环境中…...
C++入门基础:命名空间,缺省参数,函数重载,输入输出
命名空间: C语言是基于C语言的,融入了面向对象编程思想,有了很多有用的库,所以接下来我们将学习C如何优化C语言的不足的。 在C/C语言实践中,在全局作用域中变量,函数,类会有很多,这…...
tomcat 的安装与启动
文章目录 tomcat 服务器安装启动本地Tomcat服务器 tomcat 服务器安装 https://tomcat.apache.org/下载 Tomcat 10.0.X 启动本地Tomcat服务器 进入 Tomcat 的 bin...
C 语言中经典的数据结构
在 C 语言中,经典的数据结构通常包括以下几种,每种都有其特定的应用场景和实现方式: 1. 数组(Array) 定义:连续内存空间存储相同类型的数据。 特点:随机访问快(O(1))&am…...
算法-堆+单调栈
堆 首先堆在我们的Java中我们的是一个优先队列类 PriorityQueue 然后我们要弄最大堆和最小堆 最大堆: PriorityQueue<Integer> pq new PriorityQueue<Integer>((a, b) -> b - a); 最小堆: PriorityQueue<Integer> pq new P…...
物联网平台管理系统
物联网平台管理系统概述 物联网平台管理系统是物联网架构中的核心枢纽,承担着承上启下的关键作用。它向下连接各类物联网设备,实现设备的接入、管理与控制;向上为应用开发提供统一的数据接口和共性模块工具,支撑起各种丰富多彩的…...
STM32CubeMX-H7-15-SPI通信协议读写W25Q64
前言 SPI(Serial Peripheral Interface)通信协议是一种高速、全双工、同步的串行通信协议 本篇文章就使用W25Q64模块来学习SPI,包括软件SPI代码的编写,硬件SPI,中断SPI和DMASPI SPI的应用场景和模块 !这里是抄AI的&a…...
【软考】论devops在企业信息系统开发中的应用
摘要: 随着互联网的不断发展,各行各业都在建设自己的企业信息系统,而随着业务的不断升级和复杂化,系统的更新迭代速度越来越快,系统也越来越复杂。对于信息系统开发者,架构师,管理者,…...
生物化学笔记:医学免疫学原理22 肿瘤及肿瘤治疗
肿瘤及肿瘤治疗 免疫疗法 CAR-T细胞介绍...
JVM考古现场(二十二):降维打击·用二向箔优化内存模型
"警报!三维堆内存正在经历二维化坍缩!" 我腰间的玄铁令突然震动,在蜀山剑派的量子剑阵中投射出诡异的曼德博分形——这是三体文明发动降维打击的铁证! 楔子:二向箔奇点降临 昆仑镜监控日志: // …...
第三阶段面试题
Nginx nginx常用模块以及其功能 proxy模块,进行代理功能 ssl模块,进行HTTPS协议的使用 gzip模块,进行传输数据的压缩 upstream模块,进行反向代理时使用 static模块,静态资源进行访问的模块 cache模块࿰…...
操作系统-PV
🧠 背景:为什么会有 PV? 类比:内存(生产者) 和 CPU(消费者) 内存 / IO / 磁盘 / 网络下载 → 不断“生产数据” 例如:读取文件、下载视频、从数据库加载信息 CPU → 负…...
nuxt3路由切换页面出不来,刷新可以
nuxt3遇到一个奇怪的现象: 不管是router.push()跳转还是navigateTo()跳转,浏览器url变了,但是页面是空白的,没加载出来,刷新之后页面正常。 解决方案: <template>下的所有内容必须套在一个div里面...
Spring Boot配置文件优先级全解析:如何优雅覆盖默认配置?
📚 一、为什么需要了解配置文件优先级? 想象一下,你正在玩一个游戏🎮,游戏里有默认设置,但你可以通过不同的方式修改这些设置: 游戏内置的默认设置(就像Spring Boot的默认配置&…...
医院数据中心智能化数据上报与调数机制设计
针对医院数据中心的智能化数据上报与调数机制设计,需兼顾数据安全性、效率性、合规性及智能化能力。以下为系统性设计方案,分为核心模块、技术架构和关键流程三部分: 一、核心模块设计 1. 数据上报模块 子模块功能描述多源接入层对接HIS/LIS/PACS/EMR等异构系统,支持API/E…...
Linux之基础命令
Linux作为开源操作系统的代表,以其高效、灵活和强大的命令行工具闻名。无论是系统管理、开发调试还是日常使用,掌握基础命令都是与Linux系统交互的必备技能。本文整理了20个最常用的Linux基础命令,帮助新手快速入门。 目录 目录与文件导航文…...
【MATLAB代码例程】AOA与TOA结合的高精度平面地位,适用于四个基站的情况,附完整的代码
本代码实现了一种基于到达角(AOA) 和到达时间(TOA) 的混合定位算法,适用于二维平面内移动或静止目标的定位。通过4个基站的协同测量,结合最小二乘法和几何解算,能够有效估计目标位置,并支持噪声模拟、误差分析和可视化输出。适用于室内定位、无人机导航、工业监测等场景…...
PC主板及CPU ID 信息、笔记本电脑唯一 MAC地址获取
🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️ 文章目录 PC主板及CPU ID 信息物理 MAC地址获取win11 新电脑 wmic 安装❤️ 欢迎一起学AI…...
RK3568笔记八十二: 利用AI生成的简单数据转发服务程序
若该文为原创文章,转载请注明原文出处。 测试AI编写代码能力,做了个简单的数据转发功能,后期想部署到服务器 功能相对简单,大概功能如下: 1、打开TCP服务端,等待客户端连接 2、客户端连接后发送ID:1234格式,服务端收到,解析出ID:1234并记录 3、相同的ID数据之间互…...
C++17 信号量模拟实现
C17 信号量模拟实现 一、实现原理 C17 标准库没有原生信号量(C20才有),但可以通过 std::mutex std::condition_variable 模拟实现。以下是核心逻辑: #include <mutex> #include <condition_variable>class CountingSemaphore { private:…...
web后端语言中篇
#作者:允砸儿 #日期:乙巳青蛇年 三月十八 笔者本来打算隔一天给它更完的,但是事情有点多这几天,实在是抱歉。废话不多说直接进入正题。 PHP流程控制语句 什么是流控:流程控制语句用于决定代码的执行顺序。 #注意流程控制语句…...
Spine-Leaf 与 传统三层架构:全面对比与解析
本文将详细介绍Spine-Leaf架构,深入对比传统三层架构(Core、Aggre、Access),并探讨其与Full-mesh网络和软件定义网络(SDN)的关联。通过通俗易懂的示例和数据中心网络分析,我将帮助您理解Spine-L…...
Vmware esxi 查看硬盘健康状况
起因 硬盘掉盘 - - 使用自带的命令esxcli 列出所有硬盘 esxcli storage core device list[rootlocalhost:~] esxcli storage core device list t10.NVMe____INTEL_MEMPEK1W016GAL____________________PHBT83660BYP016D____00000001Display Name: Local NVMe Disk (t10.NVMe…...
React 事件处理基础
React 中最常见的两个需求,一个是列表渲染,另一个就是绑定点击事件。 这一篇就是从最基础的按钮点击开始,分四个阶段,逐步理解 React 中事件的写法和参数传递方式。 📍阶段一:最简单的点击事件 function A…...
pandas库详解
CONTENT 基本数据结构SeriesDataFrame 数据读取与写入读取 CSV 文件写入 CSV 文件 数据清洗处理缺失值数据类型转换 数据操作索引与切片数据合并数据分组与聚合 数据可视化 基本数据结构 Series Series 属于一维标记数组,由一组数据和对应的索引构成。 import pa…...
焊接机器人的设计
一、引言 随着制造业的发展,焊接工艺在各个领域得到广泛应用。焊接机器人具有焊接质量高、效率高、劳动强度低等优点,能够满足现代制造业对焊接生产的要求。设计一款性能优良的焊接机器人,对于提高焊接生产的自动化水平和产品质量具有重要意…...
python进阶: 深入了解调试利器 Pdb
Python是一种广泛使用的编程语言,以其简洁和可读性著称。在开发和调试过程中,遇到错误和问题是不可避免的。Python为此提供了一个强大的调试工具——Pdb(Python Debugger)。 Pdb是Python标准库中自带的调试器,可以帮助…...
4.黑马学习笔记-SpringMVC(P43-P47)
1.SpringMVC简介 SpringMVC技术(更少的代码,简便)与servlet技术功能相同,属于web层开发技术。 SpringMVC是一种基于java实现MVC模型的轻量级web框架。 轻量级指的是(内存占用比较低,运行效率高)…...
