数据结构第七章(三)-树形查找:红黑树
树形查找(二)
- 红黑树
- 一、红黑树
- 1.定义
- 2.黑高
- 3.性质
- 二、插入
- 1.插入步骤
- 2.举例
- 总结
红黑树
红黑树来喽~
我们在上一篇说了二叉排序树(BST)和平衡二叉树(AVL),那么既然都有这两个了,为什么还要发明红黑树?而且红黑树看起来时间复杂度也和平衡二叉树差不多:
BST | AVL Tree | Red Black Tree | |
---|---|---|---|
Invention Time | 1960 | 1962 | 1972 |
Search | O(n) | O(log2n) | O(log2n) |
Insert | O(n) | O(log2n) | O(log2n) |
Delete | O(n) | O(log2n) | O(log2n) |
我们会发现它俩不是差不多,简直是一毛一样,但是搞出红黑树是有原因的:
平衡二叉树(AVL):插入/删除 很容易破坏“平衡”特性,需要频繁调整树的形态。如:插入操作导致不平衡,则需要先计算平衡因子,找到最小不平衡子树(时间开销大),再进行 LL/RR/LR/RL 调整
红黑树(RBT):插入/删除 很多时候不会破坏“红黑”特性,无需频繁调整树的形态。即便需要调整,一般都可以在常数级时间内完成
。
所以在实际使用中,平衡二叉树适用于以查为主,很少插入/删除的应用场景;而红黑树适用于频繁插入/删除的场景,实用性更强。
一、红黑树
1.定义
红黑树是二叉排序树,满足 左子树结点值 ≤ 根节点值 ≤ 右子树结点值;
它是二叉排序树,但是它不是普通的二叉排序树。与普通的BST相比,它有如下要求:
-
每个结点或是红色的,或是黑色的;
-
根
节点是黑
色的; -
叶
结点(外部结点、NULL结点、失败结点)均是黑
色的; -
不存在两个相邻的红结点
(即红结点的父节点和孩子结点均是黑色); -
对每个结点,从该节点到任一叶结点的简单路径上,
所含黑结点的数目相同
。
注意,我们在红黑树中说的“叶结点”并不是叶子结点了,而是叶子结点的下一层,也就是查找失败的位置的结点。
那么它的结点结构就该这么定义:
struct RBNode{ //红黑树的结点定义int key; //关键字的值RBNode* parent; //双亲结点指针RBNode* lchild; //左孩子指针RBNode* rchild; //右孩子指针int color; //结点颜色,如:可用0/1表示黑/红,也可以使用枚举型enum表示颜色
};
有个color表示结点是红色还是黑的,这和平衡二叉树中有个balance表示该结点的平衡因子异曲同工;但是这里还有一个指向双亲结点的指针,证明我们可能需要找到双亲的操作会比较多,所以直接在结构体内定义会比较方便。
上面那些红黑树的要求是什么意思呢?第一是说,这结点必须得有颜色,要么红要么黑;第二是说,如果它是一棵红黑树,那么它的根节点必是黑色的;第三是说,失败结点是黑色的(别急,马上看个图就知道了);第四是说,从上往下捋,不能有俩红结点挨着;第五是说,每个结点无论到那个叶结点的路径中,经过的黑结点数目都相同。
话不多说,上图:
我们看到这个图,就能很明显地明白红黑树里面的“叶结点”(失败结点)是什么意思了,就是方的那个“NULL”,也被叫做“外部结点”。
且我们可以看到,对每个结点,从该节点到任一叶结点的简单路径上,所含黑结点的数目相同。比如这个图中的根节点,它到任一叶结点所含的黑结点的数目都是2,再比如“17”结点,它到任一叶结点所含的黑结点的数目都是1,而且这个图中也没有两个相邻的红结点,这是一棵水灵灵的红黑树。
红黑树的定义那么多,这怎么记得住……不过道高一尺,魔高一丈,我们有个口诀,直接一下概括刚刚说的红黑树的所有定义,它就是——
左根右,根叶黑,不红红,黑路同
先别管它中二不中二,问题不大,好用就行。
这也很好理解,“左根右”是它二叉排序树的特性,“根叶黑”是指根结点、叶结点的颜色都是黑的,“不红红”是指不存在两个相邻的红结点,“黑路同”是指对每个结点,从该节点到任一叶结点的简单路径上,所含黑结点的数目相同,简单易懂,朗朗上口,奈斯~
那么我们刚刚看到了一棵活的红黑树,现在我们来看看不符合红黑树要求的是啥样的:
这个一看就知道,它不满足“不红红”,有两个红的相邻了,所以不是红黑树;
这个违反了什么?违反了“根叶黑”呀,它的根是红色的不是黑色的,所以也不是红黑树;
这个违反了什么?藏得比较深,它违反了“根路同”。你看它从结点“8”去任一叶结点, “8——1——NULL” 经过的黑色结点是2个,但是“8——1——6——NULL”经过的黑色结点是3个,所以也不是红黑树;
但是如果这个结点“6”变成红色,那就满足红黑树的定义,它就变成红黑树了。
当然!!!要注意会不会给你挖坑,比如让你判断是不是红黑树,它倒是颜色没什么毛病,但你不能此时就觉得它是红黑树了啊喂!!!还要注意它是不是满足二叉排序树“左≤根≤右”的要求,有些题就特别阴险,这么对你,所以还是要细心,要多留意一下记得。
2.黑高
什么是“黑高”?我们来看一张图:
这里面标的bh就是“黑高”。
红黑树结点的黑高 bh ——从某结点出发(不含该节点)到达任一空叶结点的路径上黑结点总数
其实也就是“黑路同”中的“黑路”,这能让我们更加直观比较看看黑路同不同。
这就引申出一个问题:
根节点黑高为h的红黑树,内部结点数(关键字)至少有多少个?
注意,此处的“内部结点”说法对应于把失败结点称为“外部结点”,简单来说“内部结点”就是我们这些红黑树图里圆形的结点,“外部结点”就是我们这些红黑树图里方形的NULL结点。
那么我们内部结点最少是什么情况?既要满足红黑树定义“左根右,根叶黑,不红红,黑路同”,又要内部结点最少,所以最少情况不就是全都是黑的嘛?又因为要“黑路同”,所以就应该是一棵满二叉树。
举个栗子,比如bh=2,根节点黑高为2的内部结点最少情况应该是这样的:
so
内部结点数最少的情况——总共h层黑结点的满树形态
又因为h层一共有2h-1 个结点,所以 若根结点黑高为h,内部结点数(关键字)最少有2h-1 个。
3.性质
现在我们已经知道了红黑树是什么,那么由红黑树的定义可以得出红黑树的性质:
- 从根节点到叶结点的最长路径不大于最短路径的2倍
- 有n个内部节点的红黑树高度 h ≤ 2log2(n+1)
性质1是为什么呢?因为我们的“不红红”。最短就是没有红的,最长就是两个黑的中间夹一个红的,所以最长路径不大于最短路径的2倍;
性质2我们刚刚说黑高的时候说了,若根结点黑高为h,内部结点数(关键字)最少有2h-1 个
还有,若红黑树总高度 = h,则根节点黑高 ≥ h/2。因为根节点的黑高(从根到叶子的路径上黑色结点数)至少是树总高度h的一半,要么占完,要么插一些红结点,至少是一半。
so因为红黑树总高度 = h,根节点黑高 ≥ h/2,又因为若根结点黑高为h,内部结点数(关键字)最少有2h-1 个,所以内部结点数 n ≥ 2h/2 - 1 ,由此推出 h ≤ 2log2(n+1)。
由性质2可知,红黑树查找操作时间复杂度为 O(log2n),查找效率与AVL树同等数量级。
红黑树的查找与ASL相同,从根出发,左小右大,若查找到一个空叶结点,则查找失败。
二、插入
还记得我们平衡二叉树的插入吗?插入后要先看平不平衡,不平衡要通过旋转调整成平衡,其实万变不离其宗,我们红黑树也是。插入后要看有没有破坏红黑树的定义,破坏了也要调整,调整到还是一棵红黑树,这就是插入完成。
1.插入步骤
- 先查找,确定插入位置(原理同二叉排序树),插入新结点
- 新结点是 根——染为黑色
- 新结点 非根——染为
红色
- 若插入新结点后依然满足红黑树定义,则插入结束
- 若插入新结点后不满足红黑树定义,需要调整,使其重新满足红黑树定义
- 黑叔:旋转+染色
- LL型:右单旋,父换爷+染色
- RR型:左单旋,父换爷+染色
- LR型:左、右双旋,儿换爷+染色
- RL型:右、左双旋,儿换爷+染色
红
叔:染色+变新- 叔父爷染色,爷变为新结点
- 黑叔:旋转+染色
2.举例
我们来看一个栗子,方便我们更好地理解
从一棵空的红黑树开始,插入: 20, 10, 5, 30, 40, 57, 3, 2, 4, 35, 25, 18, 22, 23, 24, 19, 18
首先是插入结点“20”,那么由上面的红黑树插入步骤可知,当插入的新结点为根时,染成黑色,所以现在的红黑树是这个样子的:
此时我们要判断插入新结点后满不满足红黑树定义,发现是满足我们那个口诀的,所以插入完成。
接下来插入的是结点“10”,根据二叉排序树那样插入,应该插到“20”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
此时我们要判断插入新结点后满不满足红黑树定义,发现是满足我们那个口诀的(左根右,根叶黑,不红红,黑路同),所以插入完成。
其实哈,我们后面判断满不满足红黑树的性质,只要看满不满足“不红红”就行了。为啥咧?因为我们插入是按照二叉排序树插入方法,所以不会破坏“左根右”;新结点不是根的话,也不会破坏“根叶黑”;新结点不是根就给染成红色,红色是不会增加“黑路同”的;所以就一个“不红红”容易被破坏,so我们按照上面的红黑树插入步骤插入的时候判断满不满足红黑树定义,这是一个快捷的办法。
下面插入的是结点“5”,根据二叉排序树那样插入,应该插到“10”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
显然,我们插入新结点后不满足红黑树定义,需要调整,使其重新满足红黑树定义。怎么调整?要按照双亲的兄弟结点的颜色来,也就是看叔结点的颜色进行不同的步骤来调整,就是上面说的这样:
- 若插入新结点后不满足红黑树定义,需要调整,使其重新满足红黑树定义
- 黑叔:旋转+染色
- LL型:右单旋,父换爷+染色
- RR型:左单旋,父换爷+染色
- LR型:左、右双旋,儿换爷+染色
- RL型:右、左双旋,儿换爷+染色
红
叔:染色+变新- 叔父爷染色,爷变为新结点
- 黑叔:旋转+染色
显然我们新结点“5”有一个“黑叔”(NULL)(弱弱说以及……现在大概能理解为啥要把失败结点也当做红黑树的一部分并且染黑了,因为方便找“叔”和观察“叔”的颜色),那么有“黑叔”,我们应该先旋转再变色。
旋转:
看新结点是“LL”型,所以我们应该进行右单旋,由上一篇我们知道,右单旋是转“儿子”,所以也就是这样:
染色:
我们转的是“儿子”,所以把“儿子”和“爷”染色(注意,这里说的“儿子”是相对于插入新结点的爷结点说的,“爷”是相对于插入的新结点说的),也就是结点“10”和结点“20”染色,就是下面这样,我们调整完成:
接下来插入的是结点“30”,根据二叉排序树那样插入,应该插到“20”的右子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
也可以显然看到,这个违反了“不红红”,所以插入新结点后不满足红黑树定义,需要调整,使其重新满足红黑树定义,还是要按照叔的颜色来,也就还是这样:
- 若插入新结点后不满足红黑树定义,需要调整,使其重新满足红黑树定义
- 黑叔:旋转+染色
- LL型:右单旋,父换爷+染色
- RR型:左单旋,父换爷+染色
- LR型:左、右双旋,儿换爷+染色
- RL型:右、左双旋,儿换爷+染色
红
叔:染色+变新- 叔父爷染色,爷变为新结点
- 黑叔:旋转+染色
可以看到我们新结点“30”有一个“红叔”结点“5”,有“红叔”,我们应该染色+变新。
染色:
把新节点的“叔父爷”进行染色,也就是基于自身换个颜色,黑变红红变黑,也就是下面这样:
变新:
变新是指爷结点变为新结点,也就是把爷结点当做新插入的结点。那么我们新插入一个结点,首先要干什么?判断它是不是根是吧,显然这个是根,新结点是根我们就要染成黑色,所以就是这个样子滴:
只有插入红色才会违反“不红红”,新结点染黑那就不会违反“不红红”,所以插入新结点后依然满足红黑树定义,插入结束。
然后插入的是结点“40”,根据二叉排序树那样插入,应该插到“30”的右子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
显然违反了“不红红”,我们还是要进行调整,调整看它叔的颜色。它的叔为“黑叔”NULL,所以我们应该“旋转+染色”。
旋转:
新结点是RR型,所以我们进行左单旋,也就是这样:
染色:
RR型左单旋,转的是最小不平衡子树的根节点的儿子(也就是新节点的“父”);新结点的“父”、“爷”染色,也就是“30”和“20”染色,这样:
调整完成。
下面插入新结点“57”,根据二叉排序树那样插入,应该插到“40”的右子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
显然违反了“不红红”,我们还是要进行调整,调整看它叔的颜色。它的叔为“红叔”结点“20”,所以我们应该“染色+变新”。
染色:
新节点的叔父爷染色,黑变红红变黑,也就是结点“20”,“40”,“30”变色,就是这样:
变新:
变新是指爷结点变为新结点,也就是把爷结点当做新插入的结点。那么我们新插入一个结点,首先要干什么?判断它是不是根是吧,显然这个不是根,新结点非根我们就要染成红色,它本来就是红色的,变成红色也不违反“不红红”,所以我们调整完成。
之后插入新结点“3”,根据二叉排序树那样插入,应该插到“5”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
可以看到,插入新结点后不违反“不红红”。插入新结点后依然满足红黑树定义,所以我们插入结束。
然后插入新结点“2”,根据二叉排序树那样插入,应该插到“3”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
显然违反了“不红红”,我们还是要进行调整,调整看它叔的颜色。它的叔为“黑叔”结点NULL,所以我们应该“旋转+染色”。
旋转:
新结点为LL型,应该进行右单旋,即:
染色:
LL型右单旋,转的是最小不平衡子树的根节点的儿子(也就是新节点的“父”);新结点的“父”、“爷”染色,也就是“3”和“5”染色,红变黑黑变红,就是这个样子:
调整完成。
(好多啊……怎么那么多结点……
我们再插入新结点“4”,根据二叉排序树那样插入,应该插到“5”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
显然违反了“不红红”,我们还是要进行调整,调整看它叔的颜色。它的叔为“红叔”结点“2”,所以我们应该“染色+变新”。
染色:
新节点的叔父爷染色,黑变红红变黑,也就是结点“2”,“5”,“3”变色,就是这样:
变新:
变新是指爷结点变为新结点,也就是把爷结点当做新插入的结点。那么我们新插入一个结点,首先要干什么?判断它是不是根是吧,显然这个不是根,新结点非根我们就要染成红色,它本来就是红色的,变成红色也不违反“不红红”,所以我们调整完成。
然后我们插入新结点“35”,根据二叉排序树那样插入,应该插到“40”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
可以看到,插入新结点后不违反“不红红”。插入新结点后依然满足红黑树定义,所以我们插入结束。
我们再插入新结点“25”,根据二叉排序树那样插入,应该插到“20”的右子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
可以看到,插入新结点后不违反“不红红”。插入新结点后依然满足红黑树定义,所以我们插入结束。
性能逐渐优秀……
我们再再插入新结点“18”,根据二叉排序树那样插入,应该插到“20”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
可以看到,插入新结点后不违反“不红红”。插入新结点后依然满足红黑树定义,所以我们插入结束。
然后我们再插入新结点“22”,根据二叉排序树那样插入,应该插到“25”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
显然违反了“不红红”,我们还是要进行调整,调整看它叔的颜色。它的叔为“红叔”结点“18”,所以我们应该“染色+变新”。
染色:
新节点的叔父爷染色,黑变红红变黑,也就是结点“18”,“25”,“20”变色,就是这样:
变新:
变新是指爷结点变为新结点,也就是把爷结点当做新插入的结点。那么我们新插入一个结点,首先要干什么?判断它是不是根是吧,显然这个不是根,新结点非根我们就要染成红色,它本来就是红色的。
但是!!!变成红色违反了“不红红”,所以我们应该进行调整。调整看它叔的颜色,它的叔为“红叔”结点“3”,所以我们应该“染色+变新”。
染色:
新节点的叔父爷染色,黑变红红变黑,也就是结点“3”,“30”,“10”变色,就是这样:
变新:
变新是指爷结点变为新结点,也就是把爷结点当做新插入的结点。那么我们新插入一个结点,首先要干什么?判断它是不是根是吧,显然这个是根,新结点是根我们就要染成黑色,所以把爷结点(现在的新结点)“10”染成黑色,就是这样:
只有插入红色才会违反“不红红”,新结点染黑那就不会违反“不红红”,所以插入新结点后依然满足红黑树定义,插入结束。
下面我们插入新结点“23”,根据二叉排序树那样插入,应该插到“22”的右子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
显然违反了“不红红”,我们还是要进行调整,调整看它叔的颜色。它的叔为“黑叔”结点NULL,所以我们应该“旋转+染色”。
旋转:
新结点为LR型,应该对新结点先进行左旋,再进行右旋,即
左旋:
右旋:
染色:
LR型先左旋再右旋,转的是最小不平衡子树的根节点的孙子(也就是新节点);新结点和“爷”染色,也就是“23”和“25”染色,红变黑黑变红,就是这个样子:
调整完成。
然后我们再插入新结点“24”,根据二叉排序树那样插入,应该插到“25”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
显然违反了“不红红”,我们还是要进行调整,调整看它叔的颜色。它的叔为“红叔”结点“22”,所以我们应该“染色+变新”。
染色:
新节点的叔父爷染色,黑变红红变黑,也就是结点“22”,“25”,“23”变色,就是这样:
变新:
变新是指爷结点变为新结点,也就是把爷结点当做新插入的结点。那么我们新插入一个结点,首先要干什么?判断它是不是根是吧,显然这个不是根,新结点非根我们就要染成红色,它本来就是红色的。
但是!!!变成红色违反了“不红红”,所以我们应该进行调整。调整看它叔的颜色,它的叔为“黑叔”结点“40”,所以我们应该“旋转+染色”。
旋转:
新结点为LR型,应该对新结点先进行左旋,再进行右旋,即
左旋:
右旋:
染色:
LR型先左旋再右旋,转的是最小不平衡子树的根节点的孙子(也就是新节点);新结点和“爷”染色,也就是“23”和“30”染色,红变黑黑变红,就是这个样子:
调整完成。
然后我们再插入新结点“19”,根据二叉排序树那样插入,应该插到“18”的右子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
可以看到,插入新结点后不违反“不红红”。插入新结点后依然满足红黑树定义,所以我们插入结束。
最后一个结点!!!胜利就在前方!
我们最后插入新结点“18”,根据二叉排序树那样插入。这个是根据我们的应用场景来的,因为我们的红黑树里已经有“18”了,所以我们可以放在右边也可以放在左边,也可以看到里面有了就不插了,比较灵活不是死的。
那么我们现在给它放到原“18”结点的右子树里,也就是插到“19”的左子树上;而由上面的红黑树插入步骤我们也知道,当插入的新结点非根时,染成红色,就是这样:
显然违反了“不红红”,我们还是要进行调整,调整看它叔的颜色。它的叔为“黑叔”结点NULL,所以我们应该“旋转+染色”。
旋转:
新结点为RL型,应该对新结点先进行右旋,再进行左旋,即
右旋:
然后再进行左旋。
旋转后要进行染色:
RL型先右旋再左旋,转的是最小不平衡子树的根节点的孙子(也就是新节点);新结点和“爷”染色,也就是“18”和“18”染色,红变黑黑变红,就是这个样子:
于是我们调整完成。
啊~终于完成了,其实这样就能明显了解红黑树的插入到底是怎么回事了,确实是很麻烦,步骤要搞清楚,要注意的细节比较多。
有一个网站,这个网站上可以自己动态模拟一下刚刚红黑树的插入过程,记得勾上“Show Null Leaves”显示空叶结点,还有可以点击“pause”进行暂停查看,使用“Step Forward/Step Back”进行单步演示。
321上链接~
https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
总结
就是红黑树的插入特别复杂,情况判断有点多。先看插入的是不是根,是就黑不是就红,完了要是不满足红黑树定义就看叔的颜色,黑叔就“旋转+染色”,红叔就“染色+变新”,黑叔的染色是看你怎么转,LL、RR就是染最小不平衡子树的根和儿子,LR、RL就是染最小不平衡子树的根和孙子,红叔的染色就是新节点的叔父爷染色,完了爷结点再变为新结点,就是这样了,其他也没啥。
相关文章:
数据结构第七章(三)-树形查找:红黑树
树形查找(二) 红黑树一、红黑树1.定义2.黑高3.性质 二、插入1.插入步骤2.举例 总结 红黑树 红黑树来喽~ 我们在上一篇说了二叉排序树(BST)和平衡二叉树(AVL),那么既然都有这两个了,…...
C++篇——多态
目录 引言 1,什么是多态 2. 多态的定义及实现 2_1,多态的构成条件 2_2,虚函数 2_3,虚函数的重写 2_4,虚函数重写的两个例外 2_4_1,协变(基类与派生类虚函数返回值类型不同) 2_4_2. 析构函数的重写(基类…...
AI实时对话的通信基础,WebRTC技术综合指南
在通过您的网络浏览器进行音频和视频通话、屏幕共享或实时数据传输时,您可能并不常思考其背后的技术。推动这些功能的核心力量之一就是WebRTC。2011年由谷歌发布的这个开源项目,如今已发展成为一个高度全面且不断扩展的生态系统。尤其是在AI技术大幅突破…...
【寻找Linux的奥秘】第五章:认识进程
请君浏览 前言1. 冯诺依曼体系结构数据流动 2. 操作系统(Operating System)2.1 概念2.2 设计OS的目的2.3 如何理解“管理”2.4 系统调用和库函数概念 3. 进程3.1 基本概念3.1.1 查看进程3.1.2 创建进程 3.2 进程状态3.2.1 简单介绍3.2.2 运行&&阻…...
uniapp微信小程序-长按按钮百度语音识别回显文字
流程图: 话不多说,上代码: <template><view class"content"><view class"speech-chat" longpress"startSpeech" touchend"endSpeech"><view class"animate-block" …...
支付宝创建商家订单收款码(统一收单线下交易预创建).net开发的软件附带大型XML文件可以删除吗?AlipaySDKNet.OpenAPI.xml
支付宝创建商家订单收款码(统一收单线下交易预创建)一个程序55MB,XML就带了35MB AlipaySDKNet.OpenAPI.xml,BouncyCastle.Crypto.xml 支付宝店铺收款码创建的程序,这些文件可以不用吗 在支付宝店铺收款码创建的程序中…...
Profinet转Ethernet/IP网关模块通信协议适配配置
案例背景 在某自动化生产车间中,现有控制系统采用了西门子 S7 - 1500 PLC 作为主要控制器,负责生产流程的核心控制。同时,由于部分设备的历史原因,存在使用 AB 的 PLC 进行特定环节控制的情况。为了实现整个生产系统的信息交互与…...
4.6/Q1,GBD数据库最新文章解读
文章题目:Global burden, subtype, risk factors and etiological analysis of enteric infections from 1990-2021: population based study DOI:10.3389/fcimb.2025.1527765 中文标题:1990-2021 年肠道感染的全球负担、亚型、危险因素和病因…...
数字孪生技术:开启未来的“镜像”技术
想象一下,你拥有一个与现实世界一模一样的 “数字分身”,它不仅长得像你,行为举止、思维方式也和你毫无二致,甚至能提前预知你的下一步行动。这听起来像是科幻电影里的情节,但数字孪生技术却让它在现实中成为了可能。数…...
Java 序列化(Serialization)
一、理论说明 1. 序列化的定义 Java 序列化是指将对象转换为字节流的过程,以便将其存储到文件、数据库或通过网络传输。反序列化则是将字节流重新转换为对象的过程。通过实现java.io.Serializable接口,类可以被标记为可序列化的,该接口是一…...
Python解析Excel入库如何做到行的拆分
我们读取解析Excel入库经常会遇到这种场景,那就是行的拆分,如图: 比如我们入库,要以name为主键,可是表格name的值全是以逗号分割的多个,这怎么办呢?这就必须拆成多行了啊。 代码如下ÿ…...
信创国产化监控 | 达梦数据库监控全解析
达梦数据库(DM Database)是国产数据库的代表产品之一,在政府、金融、电信、能源等多个关键行业应用广泛,它具有高兼容性、高安全性、高可用性、高性能、自主可控等特点。随着国产化替代进程加速,达梦数据库在关键信息基…...
Parsec解决PnP连接失败的问题
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、准备环境二、DMZ三、端口映射1.Parsec设置固定端口2.路由器设置端口转发3.重启被控端Parsec四、多少一句1.有光猫管理员账号2.没有光猫管理员账号总结 前言…...
LLM笔记(二)LLM数据基础
核心目标: 构建 LLM 的数据基础,将原始文本转化为模型可处理的、包含丰富语义和结构信息的数值形式。 一、 环境与库准备 (Environment & Libraries): 必要库确认: 在开始之前,确保 torch (PyTorch深度学习框架) 和 tiktoken (OpenAI的高效BPE分词…...
让三个线程(t1、t2、t3)按顺序依次打印 A、B、C
public class ThreadWait {private static final Object lock = new Object();private static boolean t1Output=true;private static boolean t2Output=false;private static boolean t3Output=false;public static void main(String[] args) {//线程1new Thread(new Runnable…...
2、ubantu系统配置OpenSSH | 使用vscode或pycharm远程连接
1、OpenSSH介绍 OpenSSH(Open Secure Shell)是一套基于SSH协议的开源工具,用于在计算机网络中提供安全的加密通信。它被广泛用于远程系统管理、文件传输和网络服务的安全隧道搭建,是保护网络通信免受窃听和攻击的重要工具。 1.1…...
idea启动报错:java: 警告: 源发行版 11 需要目标发行版 11(亲测解决)
引起原因 idea的jdk没有替换干净 1.配置project file–Project Structrue–Project 2.配置Modules-Sources file–Project Structrue–Modules-Sources 改为jdk11 3.配置Modules-Dependencies file–Project Structrue–Modules-Dependencies...
Pycharm IDEA加载大文件时报错:The file size exceeds configured limit
解决方案:配置一下idea.properties文件 文件里面写入代码: idea.max.intellisense.filesize50000重启IDEA即可;...
视频分辨率增强与自动补帧
一、视频分辨率增强 1.传统分辨率增强方法 传统的视频分辨率增强方法主要基于插值技术。这些方法通过对低分辨率视频帧中已知像素点的分布规律和相邻像素之间的相关性进行分析,在两者之间插入新的像素点以达到增加视频分辨率的目的。例如,最近邻插值算…...
深度学习让鱼与熊掌兼得
通常,一个大的复杂的模型的loss会低,但是拟合方面不够,小的模型在拟合方面更好,但是loss高,我们可以通过深度学习来得到一个有着低loss的小模型 我们之前学过,peacewise linear可以用常数加上一堆这个阶梯型函数得到,然后因为peacewise linear可以逼近任何function,所以理论上…...
面试 Linux 运维相关问题
标题Q1Shell脚本是什么、它是必需的吗? Shell脚本是一种用于自动化执行命令行任务的脚本程序,通常运行在Unix/Linux系统的Shell环境中(如Bash)。它通过将多个命令、逻辑控制(如条件判断、循环)和系统功能整合到一个文…...
阿里巴巴 1688 数据接口开发指南:构建自动化商品详情采集系统
在电商行业数据驱动决策的趋势下,高效获取商品详情数据成为企业洞察市场、优化运营的关键。通过阿里巴巴 1688 数据接口构建自动化商品详情采集系统,能够快速、精准地采集海量商品信息。本文将从开发准备、接口分析、代码实现等方面,详细介绍…...
python的宫崎骏动漫电影网站管理系统
目录 技术栈介绍具体实现截图系统设计研究方法:设计步骤设计流程核心代码部分展示研究方法详细视频演示试验方案论文大纲源码获取/详细视频演示 技术栈介绍 Django-SpringBoot-php-Node.js-flask 本课题的研究方法和研究步骤基本合理,难度适中…...
答题pk小程序道具卡的获取与应用
道具卡是答题PK小程序中必不可少的一项增加趣味性的辅助应用,那么道具卡是如何获取与应用的呢,接下来我们来揭晓答案: 一、道具卡的获取: 签到获取:在每日签到中签到不仅可获得当日的签到奖励积分,同时连…...
从零开始创建一个 Next.js 项目并实现一个 TodoList 示例
Next.js 是一个基于 React 的服务端渲染框架,它提供了很多开箱即用的功能,如自动路由、API 路由、静态生成、增量静态再生等。本文将带你一步步创建一个 Next.js 项目,并实现一个简单的 TodoList 功能。 效果地址 🧱 安装 Next.j…...
全面掌握JSR303校验:从入门到实战
一、JSR303校验简介 JSR303是Java EE 6中的一项规范,全称为"Bean Validation 1.0",它定义了一套基于注解的JavaBean校验机制。通过简单的注解,我们可以优雅地完成参数校验工作,避免在业务代码中编写大量的校验逻辑。 …...
「Java EE开发指南」如何使用MyEclipse的可视化JSF编辑器设计JSP?(二)
Visual JSF Designer(可视化JSF设计器)的目标是使创建JSF应用程序的特定于组件工作更容易可视化,在本教程中,您将使用可视化设计器设计JSF登录页面。您将学习如何: 创建一个JSF项目创建一个新的JSF页面设计JSF页面 该…...
Python 翻译词典小程序
一、概述 本工具是基于Python开发的智能翻译系统,采用有道词典进行翻译,并具有本地词典缓存以及单词本功能。 版本号:v1.0 (2025-05-15) 二、核心功能说明 1. 基础翻译功能 即时翻译:输入英文单词自动获取中文释义 词性识别&…...
kafka调优
以下是 Kafka 性能调优的核心策略与参数配置建议,综合生产环境和硬件层面的优化方案,覆盖生产者、消费者、Broker 三个关键组件: 一、生产者调优 批量发送优化 • batch.size:增大批量消息大小(默认 16KB,建…...
【hadoop】sqoop案例 hive->mysql
将temperature.log中的气象数据导入到Hive的temperature表中, 根据气象站id分组计算每个气象站30年来的*最高*气温, 然后将统计结果导出到MySQL当中。 思路: 1.在hive中创建表 2.数据导入到表中 3.计算后的结果写入另外的表 4.用sqoop导出…...
Git/GitLab日常使用的命令指南来了!
在 GitLab 中拉取并合并代码的常见流程是通过 Git 命令来完成的。以下是一个标准的 Git 工作流,适用于从远程仓库(如 GitLab)拉取代码、切换分支、合并更新等操作。 🌐 一、基础命令:拉取最新代码 # 拉取远程仓库的所…...
遗传算法求解旅行商问题分析
目录 一、问题分析 二、实现步骤 1)初始化种群 2)计算适应度 3)选择操作 4)交叉操作 5)变异操作 三、求解结果 四、总结 本文通过一个经典的旅行商问题,详细阐述在实际问题中如何运用遗传算法来进…...
【Hadoop】伪分布式安装
【Hadoop】伪分布式安装 什么是 Hadoop 伪分布式安装? Hadoop 伪分布式安装(Pseudo-Distributed Mode) 是一种在单台机器上模拟分布式集群环境的部署方式。它是介于 本地模式(Local Mode) 和 完全分布式模式…...
微服务概述
什么是微服务 微服务是一个架构方案,属于分布式架构的一种。 微服务提倡将模块以独立服务的方式独立管理,整个项目依靠多个小型的服务(单独进程)同时运作来支撑,单个服务只关注自己的业务实现并且有专业的团队进行开发。服务之间使用轻量的协议进行消息传送,并且对于单个…...
【网工】华为配置基础篇①
目录 ■华为设备登录配置 ■VLAN与VLANIF地址配置 ■DHCP配置命令 ■ACL访问控制列表配置 ■NAT地址转换配置 ■华为设备登录配置 <AR> system-view //进入系统模式 [AR]sysname Huawei //设备命名为Huawei [Huawei] telnet server enable //开启设备telnet功…...
React19源码系列之 Diff算法
在之前文章中root.render执行的过程,beginWork函数是渲染过程的核心,其针对不同类型的fiber进行不同的更新处理,在FunctionComponent(函数组件)中,会针对新旧fiber进行对比处理生成新fiber。因此此次就详细…...
华为2024年报:鸿蒙生态正在取得历史性突破
华为于2025年03月31日发布2024年年度报告。报告显示,华为经营结果符合预期,实现全球销售收入 8,621 亿元人民币,净利润 626 亿元人民币。2024 年研发投入达到 1,797 亿元人民币,约占全年收入的 20.8%,近十年累计投入的…...
如何在Firefox火狐浏览器里-安装梦精灵AI提示词管理工具
第一步:进入《梦精灵跨平台AI提示词管理工具》官网 梦精灵 跨平台AI提示词管理助手 - 官网梦精灵是一款专为AI用户打造的跨平台提示词管理插件,支持一键收藏、快速复制、智能分类等功能,适用于即梦、豆包、Kimi、DeepSeek等多个AI平台&…...
【鸿蒙开发】性能优化
语言层面的优化 使用明确的数据类型,避免使用模糊的数据类型,例如ESObject。 使用AOT模式 AOT就是提前编译,将字节码提前编译成机器码,这样可以充分优化,从而加快执行速度。 未启用AOT时,一边运行一边进…...
Makefile与CMake
一、Makefile 核心内容 1. Makefile 基础结构与工作原理 三要素: 目标(Target):要生成的文件或执行的操作(如可执行文件、清理操作)。依赖(Dependency):生成目标所需的…...
P8803 [蓝桥杯 2022 国 B] 费用报销
P8803 [蓝桥杯 2022 国 B] 费用报销 - 洛谷 题目描述 小明在出差结束后返回了公司所在的城市,在填写差旅报销申请时,粗心的小明发现自己弄丢了出差过程中的票据。 为了弥补小明的损失,公司同意小明用别的票据进行报销,但是公司财…...
11 web 自动化之 DDT 数据驱动详解
文章目录 一、DDT 数据驱动介绍二、实战 一、DDT 数据驱动介绍 数据驱动: 现在主流的设计模式之一(以数据驱动测试) 结合 unittest 框架如何实现数据驱动? ddt 模块实现 数据驱动的意义: 通过不同的数据对同一脚本实现…...
15:00开始面试,15:06就出来了,问的问题有点变态。。。
从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到4月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%…...
深入理解浏览器渲染引擎:底层机制与性能优化实战
现代浏览器背后是一个庞大而复杂的系统工程,渲染引擎作为核心模块之一,承担着从解析 HTML/CSS 到最终绘制页面的关键职责。本文将从底层机制出发,系统梳理渲染引擎(如 Blink)工作原理、V8 与渲染流程的协作方式&#x…...
【LeetCode 热题 100】56. 合并区间 —— 一文弄懂排序+遍历经典解法(附Python代码)
📌 题目链接 LeetCode 56. 合并区间 📖 一、引言:区间合并,刷题路上的绊脚石? 区间类问题是算法面试中常见的经典题型,尤其是“合并区间”问题,考察你对排序、区间重叠判断及边界处理的理解和编码能力。 很多同学在面对这题时,容易卡在: 什么时候两个区间算重叠?…...
使用Mathematica绘制Clifford奇异吸引子
Clifford Attractors 是一种由微分方程 生成的混沌吸引子,参数a,b,c,d不同会产生不同的分形图案。这类吸引子属于迭代函数系统,通过不断迭代参数方程来生成复杂的图形。其数学基础可能与 Clifford 代数或高维函数理论相关,例如 Clifford 代数…...
各个历史版本mysql/tomcat/Redis/Jdk/Apache下载地址
mysql 各版本下载地址: https://downloads.mysql.com/archives/community/ **************************************************************** tomcat 各版本下载地址: https://archive.apache.org/dist/tomcat/ ********************************…...
全面解析机器学习与深度学习中的模型权重文件格式与应用场景
概述 随着机器学习和人工智能技术的飞速发展,高效且安全地存储、共享和部署训练有素的模型的方法变得越来越重要。模型权重文件格式在这个过程中发挥着关键作用。这些格式不仅保存了模型的学习参数,还能够实现可复现性,并且便于在各种不同环…...
鸿蒙OSUniApp 实现的地图定位与导航功能#三方框架 #Uniapp
UniApp 实现的地图定位与导航功能 随着移动互联网的发展,地图定位与导航功能已成为众多应用的标配。本文将详细介绍如何在 UniApp 框架下实现地图定位与导航功能,并探讨如何适配鸿蒙系统,助力开发者打造更加流畅的地图体验。 前言 最近在做一…...
【HarmonyOS 5】鸿蒙星闪NearLink详解
【HarmonyOS 5】鸿蒙星闪NearLink详解 一、前言 鸿蒙星闪NearLink Kit 是 HarmonyOS 提供的短距离通信服务,支持星闪设备间的连接、数据交互。例如,手机可作为中心设备与外围设备(如鼠标、手写笔、智能家电、车钥匙等)通过星闪进…...