数据结构和算法(11):红黑树

news2024/11/16 16:22:56

概述

伸展树实现简便、无需修改节点结构、分摊复杂度低,但可惜最坏情况下的单次操作需要O(n)时间。
AVL树尽管可以保证最坏情况下的单次操作速度,但需在节点中嵌入平衡因子等标识;更重要的是,删除操作之后的重平衡可能需做多达O(logn)次旋转,从而频繁地导致全树整体拓扑结构的大幅度变化。

红黑树通过为节点指定颜色,并巧妙地动态调整,红黑树可保证:在每次插入或删除操作之后的重平衡过程中,全树拓扑结构的更新仅涉及常数个节点。尽管最坏情况下需对多达O(logn)个节点重染色,但就分摊意义而言仅为O(1)个。

在AVL树“适度平衡”标准的基础上,进一步放宽条件:任一节点左、右子树的高度,相差不得超过两倍

接口和定义

统一地引入n + 1个外部节点,以保证原树中每一节点(现称作内部节点,白色八角形)的左、右孩子均非空——尽管有可能其中之一甚至二者同时是外部节点。当然,这些外部节点的引入只是假想式的,在具体实现时并不一定需要兑现为真实的节点。
在这里插入图片描述

定义

由红、黑两色节点组成的二叉搜索树若满足以下条件,即为红黑树(red-black tree):
(1) 树根始终为黑色;
(2) 外部节点均为黑色;
(3) 其余节点若为红色,则其孩子节点必为黑色;
(4) 从任一外部节点到根节点的沿途,黑节点的数目相等。

条件(1)和(2)意味着红节点均为内部节点,且其父节点及左、右孩子必然存在。另外,条件(3)意味着红节点之父必为黑色,因此树中任一通路都不含相邻的红节点
在从根节点通往任一节点的沿途,黑节点都不少于红节点。除去根节点本身,沿途所经黑节点的总数称作该节点的黑深度(black depth)——根节点的黑深度为0,其余依此类推。故条件(4)亦可等效地理解和描述为“所有外部节点的黑深度统一

除去(黑色)外部节点,沿途所经黑节点的总数称作该节点的黑高度(black height)。如此,所有外部节点的黑高度均为0,其余依此类推。

根节点的黑高度亦称作全树的黑高度,在数值上与外部节点的黑深度相等。

(2,4)树

在红黑树与4阶B-树之间,存在极其密切的联系;经适当转换之后,二者相互等价!

具体地,自顶而下逐层考查红黑树各节点:每遇到一个红节点,都将对应的子树整体提升一层,从而与其父节点(必黑)水平对齐,二者之间的联边则相应地调整为横向。
如此转换之后,横向边或向左或向右,但由红黑树的条件(3),同向者彼此不会相邻;即便不考虑联边的左右方向,沿水平方向相邻的边至多两条(向左、右各一条),涉及的节点至多三个(一个黑节点加上零到两个红节点)。此时,若将原红黑树的节点视作关键码,沿水平方向相邻的每一组(父子至多三个)节点即恰好构成4阶B-树的一个节点。

在这里插入图片描述
(2,4)-树中的每个节点应包含且仅包含一个黑关键码,同时红关键码不得超过两个。而且,若某个节点果真包含两个红关键码,则黑关键码的位置必然居中。

平衡性

红黑树的黑高度不低二高度的一半;反之,高度不超过黑高度的两倍。
在这里插入图片描述
红黑树的性能首先取决于其平衡性。

n个内部节点的红黑树T的高度h也不致超过O(logn) log ⁡ 2 ( n + 1 ) ≤ h ≤ 2 ⋅ log ⁡ 2 ( n + 1 ) \log_2(n+1)\leq h \leq 2 \cdot \log_2(n+1) log2(n+1)h2log2(n+1)
尽管红黑树不能如完全树那样可做到理想平衡,也不如AVL树那样可做到较严格的适度平衡,但其高度仍控制在最小高度的两倍以内,渐进的角度看仍是O(logn),依然保证了适度平衡。

#include "../BST/BST.h”	//基于BST实现RedBlack
template <typename T> class RedBlack : public BST<T> { 	//RedBlack树模板类
protected:
	void solveDoubleRed ( BinNodePosi(T) x );	//双红修正
	void solveDoubleBlack ( BinNodePosi(T) x );	//双黑修正
	int updateHeight ( BinNodePosi(T) x );		//更新节点x的高度
public:
	BinNodePosi(T) insert ( const T&e );	//插入(重写)
	bool remove ( const T&e );	//删除(重写)
//BST::search()等其余接口可直接沿用
};

节点插入算法

经调用接口search(e)做查找之后,确认目标节点尚不存在。
于是,在查找终止的位置x处创建节点,并随即将其染成红色(除非此时全树仅含一个节点)。
现在,对照红黑树的四项条件,唯有(3)未必满足——亦即,此时x的父亲也可能是红色。

红黑树insert()接口

templatetypename T> BinNodePosi(T) RedBlack<T>::insert ( const T& e ) { //将e插入红黑树
	BinNodePosi(T) & x = search ( e ); if ( x ) return x;		//确认目标不存在(留意对_hot的设置)
	x = new BinNode<T> ( e,_hot,NULLNULL-1 ); _size++;	//创建红节点x︰以_hot为父,黑高度-1
	solveDoubleRed ( x ); return x ? x : _hot->parent;			//经双红修正后,即可返回
}	//无论e是否存在于原树中,返回时总有x->data == e

因新节点的引入,而导致父子节点同为红色的此类情况,称作双红
调用solveDoubleRed(x)接口。每引入一个关键码,该接口都可能迭代地调用多次。在此过程中,当前节点x的兄弟及两个孩子(初始时都是外部节点),始终均为黑色。
x的父亲与祖父分别记作pg。既然此前的红黑树合法,故作为红节点p的父亲,g必然存在且为黑色。g作为内部节点,其另一孩子(即p的兄弟、x的叔父)也必然存在,将其记作u

视节点u的颜色不同,分两类情况分别处置:
1.双红修正(RR-1)
考查u为黑色的情况。此时,x的兄弟、两个孩子的黑高度,均与u相等。
图(a)和(b)为此类情况的两种可能:
在这里插入图片描述此时红黑树条件(3)的违反,从B-树角度等效地看,即同一节点不应包含紧邻的红色关键码。如图(c’)所示,只需令黑色关键码与紧邻的红色关键码互换颜色。从图©红黑树的角度看,这等效于按中序遍历次序,对节点xpg及其四棵子树,做一次局部“3 + 4”重构。

如此调整之后,局部子树的黑高度将复原,这意味着全树的平衡也必然得以恢复。
同时,新子树的根节点b为黑色,也不致引发新的双红现象。至此,整个插入操作遂告完成

2.双红修正(RR-2 )
再考查节点u为红色的情况。此时,u的左、右孩子非空且均为黑色,其黑高度必与x的兄弟以及两个孩子相等。
在这里插入图片描述上方、下方分别为红黑树及其对应B-树的局部

图(a)和(b)给出了两种可能的此类情况。此时红黑树条件(3)的违反,从B-树角度等效地看,即该节点因超过4度而发生上溢。
从图©红黑树的角度来看,只需将红节点pu转为黑色,黑节点g转为红色,x保持红色。从图(c’)B-树的角度来看,等效于上溢节点的一次分裂。
如此调整之后局部子树的黑高度复原。然而,子树根节点g转为红色之后,有可能在更高层再次引发双红现象。
从图(c’)B-树的角度来看,对应于在关键码g被移出并归入上层节点之后,进而导致上层节点的上溢——即上溢的向上传播。
若果真如此,可以等效地将g视作新插入的节点,同样地分以上两类情况如法处置。每经过一次这样的迭代,节点g都将在B-树中(作为关键码)上升一层,而在红黑树中存在双红缺陷的位置也将相应地上升两层,故累计至多迭代O(logn)次。
若最后一步迭代之后导致原树根的分裂,并由g独立地构成新的树根节点,则应遵照红黑树条件(1)的要求,强行将其转为黑色——如此,全树的黑高度随即增加一层。

双红修正的复杂度

在这里插入图片描述对于前一种情况,只需做一轮修正;
后一种情况虽有可能需要反复修正,但由于修正位置的高度会严格单调上升,故总共也不过O(logn)轮。
每一轮修正只涉及到常数次的节点旋转或染色操作。因此,节点插入之后的双红修正,累计耗时不会超过O(logn)。即便计入此前的关键码查找以及节点接入等操作,红黑树的每次节点插入操作,都可在O(logn)时间内完成。

只有在RR-1修复时才需做1~2次旋转;而且一旦旋转后,修复过程必然随即完成。故就全树拓扑结构而言,每次插入后仅涉及常数次调整;而且稍后将会看到,红黑树的节点删除操作亦是如此。

实现

//*RedBlack双红调整算法︰解决节点x与其父均为红色的问题。分为两大类情况︰
//*RR-1∶2次颜色翻转,2次黑高度更新,1~2次旋转,不再递归
//*RR-2∶3次颜色翻转,3次黑高度更新,0次旋转,需要递归

template <typename T> void RedBlackT>: :solveDoubleRed ( BinNodePosi(T) x ) {	//x当前必为红
	if ( IsRoot ( *x ) )//若已(递归)转至树根,则将其转黑,整树黑高度也随之递增
		{ _root->color = RB_BLACK; _root->height++; return; }	//否则,x的父亲p必存在
	BinNodePosi(T) p = x->parent; if ( IsBlack ( p ) ) return;	//若p为黑,则可终止调整。否则			
	BinNodePosi(T) g = p->parent;	//既然p为红,则x的祖父必存在,且必为黑色
	BinNodePosi(T) u = uncle ( x );	//以下,视x叔父u的颜色分别处理
	if ( IsBlack ( u ) ) { //u为黑色(含NULL)时
		if ( IsLChild ( *x ) == IsLChild ( *p ))//若x与p同侧(即zIg-zIg或zAg-zAg ),则
			p->color = RB_BLACK;	//p由红转黑,x保持红
		else 	//若x与p异侧(即zIg-zAg或zAg-zIg ),则
			x->color = RB_BLACK;//x由红转黑,p保持红
		g->color = RB_RED; //g必定由黑转红
//以上虽保证总共两次染色,但因增加了判断而得不偿失
//在旋转后将根置黑、孩子置红,虽需三次染色但效率更高
		BinNodePosi(T) gg = g->parent;	//曾祖父( great-grand parent )
		BinNodePosi(T) r = FromParentTo ( *g ) = rotateAt ( x );	//调整后的子树根节点
		r->parent = gg; //与原曾祖父联接
	}else { //若u为红色
		p->color = RB_BLACK; p->height++; 	//p由红转黑
		u->color = RB_BLACK; u->height++;	//u由红转黑
		if ( !IsRoot ( *g ) ) g->color = RB_RED;	//g若非根,则转红
		solveDoubleRed ( g );	//继续调整g(类似于尾递归,可优化为迭代形式)
	}
}

节点删除算法

接口

template <typename T> bool RedBlack<T>::remove ( const T& e ) {//从红黑树中删除关键码e
	BinNodePosi(T)& x = search ( e ); if ( !x ) return false;//确认目标存在(留意_hot的设置)
	BinNodePosi(T) r = removeAt ( x,_hot ); if ( ! ( --_size ) ) return true;//实施删除
// assert: _hot某一孩子刚被删除,且被r所指节点(可能是NULL)接替。以下检查是否失衡,并做必要调整
	if ( ! _hot )//若刚被删除的是根节点,则将其置黑,并更新黑高度
		{ _root->color = RB_BLACK; updateHeight ( _root ); return true; }
//assert:以下,原x(现r)必非根,_hot必非空
	if ( BlackHeightUpdated ( *_hot ) ) return true;	//若所有祖先的黑深度依然平衡,则无需调整
	if ( IsRed ( r ) )	//否则,若r为红,则只需令其转黑
		{ r->color = RB_BLACK; r->height++; return true; }
//assert:以下,原x(现r)均为黑色
	solveDoubleBlack ( r ); return true;	//经双黑调整后返回
}//若目标节点存在且被删除,返回true;否则返回false

首先调用标准接口BST::search(e),查找目标节点x。若查找成功,则调用内部接口removeAt(x)实施删除。其间无论是否做过一次节点交换,均以r指向实际被删除节点x的接替者,p = _hot为其父亲。
此时红黑树的前两个条件继续满足,但后两个条件却未必依然满足。

除了其接替者rx 还应有另一个孩子w。既然x是实际被删除者,故 w 必为(黑色的)外部节点 NULL
在这里插入图片描述
如图 (a) 和 (a’) 所示,若 x 为红色,则在删除x并代之以r后,条件(3~4)依然满足;反之,若x为黑色,则要看其替代者r的颜色。
如图 (b) 和 (b’) 所示,若 r 为红色,则只需将其翻转为黑色,即可使条件(3~4)重新满足。
如图 ( c) 和 (c’) 所示,若 xr 均为黑色,则为使条件(3~4)重新成立,还需要做略微复杂一些的处理。
因某一无红色孩子的黑节点被删除,而导致的此类复杂情况,称作双黑(double black)现象。此时,需从r出发调用solveDoubleBlack(r)算法予以修正。
自然,原黑节点x的兄弟必然非空,将其记作sx的父亲记作p,其颜色不确定(故在图中以八角形示意)。

sp颜色的不同组合,按四种情况分别处置:

1.双黑修正(BB-1)
节点x的另一孩子w = NULL,故从B-树角度 (a’) 看节点x被删除之后的情况,可以等效地理解为:关键码x原所属的节点发生下溢;此时,ts必然属于B-树的同一节点,且该节点就是下溢节点的兄弟。故可参照B-树的调整方法,下溢节点从父节点借出一个关键码(p),然后父节点从向下溢节点的兄弟节点借出一个关键码(s),调整后的效果如图(b')。
在这里插入图片描述
从红黑树的角度 (图(b)) 来看,上述调整过程等效于,对节点tsp实施 “3 + 4”重构。
若这三个节点按中序遍历次序重命名为abc,则还需将ac染成黑色,b则继承p此前的颜色。
tp染成黑色,s继承p此前的颜色。整个过程中节点r保持黑色不变。
经以上处理之后,红黑树的所有条件,都在这一局部以及全局得到恢复,故删除操作遂告完成。

2.双黑修正(BB-2-R)
节点s及其两个孩子均为黑色时,视节点p颜色的不同,又可进一步分为两种情况。

与BB-1类似,在对应的B-树中,关键码x的删除导致其所属的节点下溢。但因此时关键码s所在节点只有两个分支,故下溢节点无法从父节点借出关键码(p)。
在这里插入图片描述
如图(b’) 所示,将关键码p取出并下降一层,然后以之为“粘合剂”,将原左、右孩子合并为一个节点。从红黑树角度看,这
一过程可如 图(b) 所示等效地理解为:sp颜色互换。

经过以上处理,红黑树的所有条件都在此局部得以恢复。另外,由于关键码p原为红色,故如 图(a’) 所示,在关键码p所属节点中,其左或右必然还有一个黑色关键码(当然,不可能左、右兼有)——这意味着,在关键码p从其中取出之后,不致引发新的下溢。至此,红黑树条件亦必在全局得以恢复,删除操作即告完成。

3.双黑修正(BB-2-B )
考虑节点ss的两个孩子以及节点p均为黑色的情况。
在这里插入图片描述
与BB-2-R类似,在对应的B-树中,因关键码x的删除,导致其所属节点发生下溢。
图(b’) 所示,将下溢节点与其兄弟合并。从红黑树的角度来看,这一过程可如图(b)所示等效地理解为:节点s由黑转红。
图(b) 可知,经以上处理,红黑树所有条件都在此局部得到恢复。
sx在此之前均为黑色,故如 图(a’) 所示,p原所属的B-树节点必然仅含p这一个关键码。于是在p被借出之后,该节点必将继而发生下溢,故有待于后续进一步修正。
此时的状态可等效地理解为:节点p的父节点刚被删除。
这是双黑修正过程中,需要再次迭代的唯一可能。幸运的是,尽管此类情况可能持续发生,下溢的位置也必然不断上升,故至多迭代O(logn)次后必然终止。

4.双黑修正(BB-3 )

在这里插入图片描述
考虑节点s为红色的情况。
图(a) 所示,即为一种典型的此类情况。此时,作为红节点s的父亲,节点p必为黑色;同时,s的两个孩子也应均为黑色。
从B-树的角度来看,只需 如图(b’) 所示,令关键码sp互换颜色,即可得到一棵与之完全等价的B-树。而从红黑树的角度来看,这一转换对应于以节点p为轴做一次旋转,并交换节点sp的颜色。
在转换之后的红黑树中,被删除节点x(及其替代者节点r)有了一个新的兄弟s'——与此前的兄弟s不同,s'必然是黑的!这就意味着,接下来可以套用此前所介绍其它情况的处置方法,继续并最终完成双黑修正。

在这里插入图片描述
同样需要注意:现在的节点p,也已经黑色转为红色。因此接下来即便需要继续调整,必然既不可能转换回此前的情况BB-3,也不可能转入可能需要反复迭代的情况BB-2-B。

复杂度

在这里插入图片描述其中涉及的重构、染色等局部操作,均可在常数时间内完成。

在这里插入图片描述
两种情况各自只需做一轮修正,最后一种情况亦不过两轮。
情况BB-2-B虽可能需要反复修正,但由于待修正位置的高度严格单调上升,累计也不致过O(logn)轮,故双黑修正过程总共耗时不超过O(logn)。即便计入此前的关键码查找和节点摘除操作,红黑树的节点删除操作总是可在O(logn)时间内完成。
可以发现: 一旦在某步迭代中做过节点的旋转调整,整个修复过程便会随即完成。 因此与双红修正一样,双黑修正的整个过程,也仅涉及常数次的拓扑结构调整操作。

修正算法的实现

1 /******************************************************************************************
2 * RedBlack双黑调整算法:解决节点x不被其替代的节点均为黑色的问题
3 * 分为三大类共四种情冴:
4 * BB-1 :2次颜色翻转,2次黑高度更新,1~2次旋转,不再递归
5 * BB-2R:2次颜色翻转,2次黑高度更新,0次旋转,不再递归
6 * BB-2B:1次颜色翻转,1次黑高度更新,0次旋转,需要递归
7 * BB-3 :2次颜色翻转,2次黑高度更新,1次旋转,转为BB-1或BB2R
8 ******************************************************************************************/

template <typename T> void RedBlack<T>::solveDoubleBlack ( BinNodePosi(T) r ) {
	BinNodePosi(T) p = r ? r->parent : _hot; if ( !p ) return; //r的父亲
	BinNodePosi(T) s = ( r == p->lc ) ? p->rc : p->lc; //r的兄弟
	if ( IsBlack ( s ) ) { //兄弟s为黑
		BinNodePosi(T) t = NULL;//s的红孩子(若左、右孩子皆红,左者优先﹔皆黑时为NULL )
		if( HasLChild ( *s ) &8 IsRed ( s->lc ) ) t = s->lc;
		else if ( HasRChild ( *s ) && IsRed ( s->rc ) ) t = s->rc;
		if ( t ) {//黑s有红孩子︰BB-1
			RBColor oldColor = p->color;//备份原子树根节点p颜色,并对t及其父亲、祖父
			BinNodePosi(T) b = FromParentTo ( *p ) = rotateAt ( t );//重平衡,并将新子树的左、右孩子染黑
			if ( HasLChild ( *b ) ) b->lc->color = RB_BLACK; updateHeight ( b->lc );//左孩子
			if ( HasRChild ( *b ) ) b->rc->color = RB_BLACK; updateHeight ( b->rc ); //右孩子
			b->color = oldcolor; updateHeight ( b );//新子树根节点继承原根节点的颜色
		}else { //黑s无红孩子
			s->color = RB_RED; s->height--; // s转红
			if ( IsRed ( p ) ) { //BB-2R
				p->color = RB_BLACK; //p转黑,但黑高度不变
			}else { //BB-2B
				p->height--; //p保持黑,但黑高度下降
				solveDoubleBlack ( p );
			}
		}
	} else { //兄弟s为红:BB-3
		s->color = RB_BLACK; p->color = RB_RED;//s转黑,p转红
		BinNodePosi(T) t = IsLChild ( *s ) ? s->lc : s->rc; //取t与其父s同侧
		_hot = p; FromParentTo ( *p ) = rotateAt ( t );	//对t及其父亲、祖父做平衡调整
		solveDoubleBlack ( r );	//继续修正r处双黑——此时的p已转红,故后续只能是BB-1或BB-2R
	}
}

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

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

相关文章

【DRAM存储器十三】DDR介绍-功能框图和模式寄存器解析

&#x1f449;个人主页&#xff1a;highman110 &#x1f449;作者简介&#xff1a;一名硬件工程师&#xff0c;持续学习&#xff0c;不断记录&#xff0c;保持思考&#xff0c;输出干货内容 参考资料&#xff1a;《镁光DDR数据手册》 目录 DDR SDRAM芯片引脚 DDR SDRAM芯片框…

校园跑腿小程序还受欢迎不?

校园跑腿小程序是如今大学生群体中越来越受欢迎的一种服务模式。它为大学生提供了一个便捷的平台&#xff0c;使他们能够在校园内完成各类生活事务&#xff0c;如购买食品、快递取送、打印复印等。这种形式的服务在过去几年里在全球范围内迅速发展&#xff0c;并取得了巨大的成…

大学专业分类及介绍 专业有哪些

大学的专业非常多样化&#xff0c;涵盖了哲学、经济学、法学、教育学、文学、历史学、理学、工学、农学、医学、管理学、艺术学等12个学科门类。每个学科门类下又设有多个具体专业。 哲学类下设专业有4个&#xff0c;包括哲学、逻辑学、宗教学、伦理学。 经济学类下设专业有17…

外汇天眼:CONSOB下令封禁5个非法金融服务网站 总数达945个!

负责监管意大利金融市场的监管机构意大利公司和交易委员会The Commissione Nazionale per le Societ e la Borsa &#xff08;CONSOB&#xff09;10月6日发布禁令&#xff0c;命令意大利互联网服务提供商&#xff08;ISP&#xff09;关闭5个在意大利境内提供非法金融服务的网站…

【Codeforces】Educational Codeforces Round 156 [Rated for Div. 2]

hh第一次记录cf。 复盘 ab题目比较清晰&#xff0c;只开了这两题&#xff0c;后面看了下cd&#xff0c;即使开了翻译也看不懂题目是什么意思&#xff0c;最后放弃睡觉了。。 a是一道思维题&#xff0c;翻了下别人写的发现大家写的各不相同hh b是一道数学题&#xff0c;过程有点…

改element的单选框的样式,改成方形有勾的样式

element-ui单选框按钮的样式改成对钩_el-radio 变对钩样式-CSDN博客 改变选中后字体的颜色 // 改变选中后字体的颜色 ::v-deep .el-radio__input.is-checked .el-radio__label {color:#28d4c1!important; }

2.1 线程是什么

技术上来说&#xff0c;线程是操作系统能够操作运行的一组独立的指令运算流程&#xff1b;更具体地来说&#xff0c;它的意义如下。 对于开发者&#xff0c;独立于主程序运行的一个“程序”可以称为一个线程。更进一步来说&#xff0c;如果一个应用包含多个“程序”&#xff0c…

计算顺序表中值在100到500之间的元素个数

要求顺序表中值在100到500之间的元素的个数&#xff0c;你可以使用C语言编写一个循环来遍历顺序表中的元素&#xff0c;并在循环中检查每个元素是否在指定的范围内。 #include <stdio.h>#define MAX_SIZE 100 // 假设顺序表的最大容量为100int main() {int arr[MAX_SIZE]…

车载开发所学内容,有哪些?程序员的转岗位需求

一、高速发展的行业前景 随着全球智能汽车市场的飞速发展&#xff0c;车载开发行业的前景可谓一片光明。各国政府对于自动驾驶和智能交通系统的政策支持&#xff0c;为行业带来了前所未有的机遇。此外&#xff0c;人工智能、大数据、云计算等前沿技术的不断突破&#xff0c;为…

C#,数值计算——数据建模Fitlin的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// General linear fit /// </summary> public class Fitlin { private int ndat { get; set; } private int ma { get; set; } private do…

项目管理必备的22个公式

大家好&#xff0c;我是老原。 趁着国庆时间比较空闲&#xff0c;给你们整理了一些项目管理必备的计算公式&#xff0c;一共22个。 每一个公式都给你们标注了适用情况和使用方法&#xff0c;为了方便你们理解&#xff0c;也加了一些例子&#xff0c;保准你看了就会。 觉得不…

增强基于Cortex-M3的MCU以处理480 Mbps高速USB

通用串行总线&#xff08;USB&#xff09;完全取代了PC上的UART&#xff0c;PS2和IEEE-1284并行接口&#xff0c;现在已在嵌入式开发应用程序中得到广泛认可。嵌入式开发系统使用的大多数I / O设备&#xff08;键盘&#xff0c;扫描仪&#xff0c;鼠标&#xff09;都是基于USB的…

MySQL数据库基本操作-DQL-聚合查询

简介 使用聚合函数查询是纵向查询&#xff0c;它是对一列的值进行计算&#xff0c;然后返回一个单一的值&#xff1b;另外聚合函数会忽略空值。 字段说明&#xff1a; product 是一个表pname 是商品名price 是 价格category_id 是分类 -- 1 查询商品的总条数 select count(…

Ubuntu20.04系统安装cuda11.3

在官网下载cuda进行安装&#xff1a; 官网链接&#xff1a;CUDA Toolkit Archive | NVIDIA Developer 再官网版本中选择需要的版本&#xff0c;本身需要cuda11.3 cuda版本选择后&#xff0c;选择系统信息后复制命令进行下载&#xff08;我是ubuntu20.04,aarch64 架构&#xf…

清华智谱AI大模型ChatGLM-Pro申请开通教程

清华智谱AI大模型ChatGLM-Pro申请开通教程 ChatGLM系列模型&#xff0c;包括ChatGLM-130B和ChatGLM-6B模型&#xff0c;支持相对复杂的自然语言指令&#xff0c;并且能够解决困难的推理类问题。其中&#xff0c;ChatGLM-6B模型吸引了全球超过 160 万人下载安装&#xff0c;该模…

磷矿石和磷精矿中氧化镁含量的测定

声明 本文是学习GB-T 1871.5-2022 磷矿石和磷精矿中氧化镁含量的测定 火焰原子吸收光谱法、容量法和电感耦合等离子体发射光谱法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件描述了在磷矿石和磷精矿中测定氧化镁含量的火焰原子吸收…

GRADIENT BASED THRESHOLD FREE COLOR FILTER ARRAY INTERPOLATION

ABSTRACT 彩色滤波器阵列(CFA)插值是单传感器数字相机图像处理管道的组成部分。多年来&#xff0c;许多CFA算法被提出以提高图像质量。其中一个算法就是非常成功的定向线性最小均方误差估计(Directional Linear Minimum Mean-Square Error Estimation, DLMMSE)方法。我们对该算…

JavaScript使用throw new Error自定义错误信息

有些时候 我们自己写了一个组件 但是怕同事不了解我们的组件 传入了错误的类型或者数据 导致逻辑报错 同事还会觉得我们的组件写的莫名其妙 我们就可以自己写判断 例如我这个代码 我判断 如果同事传入的 type 为 false 或者 在我自己的集合中找不到 外面传入的type类型 我就直…

【G-LAB】带你掌握网络交换机上各种接口知识

点击上方关注我们 交换机是一种用于电&#xff08;光&#xff09;信号转发的网络设备。可以为接入交换机的任意两个网络节点提供独享的电信号通路。最常见的交换机是以太网交换机。其他常见的还有电话语音交换机、光纤交换机等。交换机是使用非常广泛的网络设备。多台网络设备…

十五、异常(7)

本章概要 其他可选方式 历史观点把异常传递给控制台把“检查的异常”转换为“不检查的异常” 异常指南 其他可选方式 异常处理系统就像一个活门&#xff08;trap door&#xff09;&#xff0c;使你能放弃程序的正常执行序列。当“异常情形”发生的时候&#xff0c;正常的执行…