RBTree(红黑树)的介绍和实现

   欢迎来到杀马特的主页:羑悻的小杀马特.-CSDN博客

目录

​编辑

一·红黑树介绍:

1.1红黑树概念:

1.2红黑树遵循的原则:

 1.3红黑树效率分析:

二.红黑树的实现:

2.1红黑树结构:

2.2红黑树节点的插入:

2.2.1 顺序性插入:

2.2.2.1变色(叔叔节点为红色):

 2.2.2.2变色(叔叔节点为红色)(简单总结版):

2.2.3.1 左单旋+变色(叔叔节点为黑色或者不存在):

 2.2.3.2左单旋+变色(叔叔节点为黑色或者不存在)(简单总结版):

2.2.4.1 右单旋+变色(叔叔节点为黑色或者不存在):

2.2.4.2 右单旋+变色(叔叔节点为黑色或者不存在)(简单总结版):

2.2.5.1 左右双旋+变色(叔叔节点为黑色或者不存在):

2.2.5.2 左右双旋+变色(叔叔节点为黑色或者不存在)(简单总结版):

2.2.6.1右左双旋+变色(叔叔节点为黑色或者不存在):

 2.2.6.2右左双旋+变色(叔叔节点为黑色或者不存在)(简单总结版):

 2.3红黑树的查找:​编辑

2.4红黑树的验证: 

2.5红黑树的删除:

三·代码总结: 

四·红黑树创建总结(仅个人理解): 


一·红黑树介绍:

1.1红黑树概念:

首先可以把它理解成一颗二叉搜索树,但是它的节点会有颜色不是红就是黑,可以这么理解:就是avl树把平衡因子去掉并改成颜色再加以修改,但是平衡还是有点差别,高度可能会差别大于2,因此只能勉勉强强这麽说。这样可以保证如果存在最短路径必然都是黑节点,如果存在最长路径必然一般黑一般红,其他路径就位于它们之间了,它根据特性也可以默认成平衡的了,这里也要注意空节点默认为黑色(这里也可有头结点也可无,如果有的话就是头结点为黑色,然后它的parent指针指向根节点,左指针指向树最左边孩子,右指针指向树最右边的孩子)。

1.2红黑树遵循的原则:

简称红黑树四大原则:

①它的结点不是红⾊就是⿊⾊ 。

②根结点是⿊⾊的。

③如果⼀个结点是红⾊的,则它的两个孩⼦结点必须是⿊⾊的,也就是说任意⼀条路径不会有连续的 红⾊结点,故红红节点不能连续出现。

 ④对于任意⼀个结点,从该结点到其所有NULL结点的简单路径上,均包含相同数量的⿊⾊结点。

 1.3红黑树效率分析:

这里如果我们假设树的最短高度是h,而最长高度就是2h(假设存在的话):为什么?:这里若果是最短(由于黑色节点相同)故只需要它无红色几点即全黑设高度为h,那么最长的只能是红黑交错出现(红色不能相连)故就是2h了。 那么我们证明一下它的效率范围:

这里最短路路径就是18 10 而最长就是 18 30 40 50,我们以最坏情况考虑(因为在最短和最长之间的点是怎样分布不清楚故这样)那么最好就是2^h-1,最长是2^2h-1,也就是节点是这些,设节点为n解答时间复杂度=logn与2*logn之间,故都可以近似成o(logn)。

二.红黑树的实现:

2.1红黑树结构:

这里和avl树大致相同就是把平衡因子等换成了颜色的枚举类型了。

enum Colour
{RED,BLACK
};template<class K, class V>
struct RBTreeNode
{pair<K, V> _kv;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Colour _col;RBTreeNode(const pair<K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr){}
};template<class K, class V>
class RBTree {using Node = RBTreeNode<K, V>;
public:private:
Node* _root=nullptr;};

2.2红黑树节点的插入:

这里剧透一下:那么插入过程大概是怎么样的呢?首先我们先找到了大小关系合适的节点;然后如果我们插入的是黑色就破坏了黑色相等的规则,故插入的节点一定是红色,那么就可以推出它的父亲是红或者黑,如果是黑色那么可以直接成功插入了,但是如果是红色的话,爷爷节点一定是黑色,此时关键就要看叔叔节点了:这时候分为三种情况为黑,为红,不存在(为黑),故这里还可以归总成两种:1·叔叔节点为红色,2·叔叔节点为黑色。----->"调整的环节又叫"关键看叔叔"

下面说一下这个插入的思路:就是当我们插入后父亲是黑色就退出,如果是红色:那么就继续向上调整(这里可以直到如果父亲为红肯定存在爷爷即为黑,但是爷爷的父亲不一定存在,那么如果下一次向上调整爷爷变成了孩子,那么可能爷爷就是根节点,但是会被变红,故需要最后变黑),此时就要看叔叔了。根据那两种情况进行旋转或者不旋转。 

代码思路:首先分为两大方向分别是父亲是爷爷的左孩子与右孩子,此时叔叔就相反了,然后再分叔叔为黑或者红(直接变色),为黑:则要分孩子插入的是父亲的左还是右进行对应的左 右单旋和左右 右左双旋 。

2.2.1 顺序性插入:

就是按照比原节点值小就向左走,大就向右走,然后走到空,判断插入的是左还是右进行插入即可。

if (_root == nullptr)
{_root = new Node(kv);_root->_col = BLACK;return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}
}cur = new Node(kv);
cur->_col = RED;
if (parent->_kv.first < kv.first)
{parent->_right = cur;
}
else
{parent->_left = cur;
}cur->_parent = parent;

2.2.2.1变色(叔叔节点为红色):

叔叔节点为红色的情况(这里首先要确定叔叔是爷爷的左还是右(父亲,叔叔的连接如何)):

假设插入的是c这个节点,故此时父亲是红色,故要变色(由于要保证每条路黑色节点个数不变,故我们可以先把父亲和叔叔节点变成黑色,爷爷变成红色就行了-->这样可以保证黑色节点相当于没变化。),接着就是向上调整(让爷爷节点变成孩子)看看父亲节点颜色,红色:就看叔叔颜色,进行相关变化黑色:退出。

代码实现:

if (uncle && uncle->_col == RED) {parent->_col = uncle->_col = BLACK;grandfather->_col = RED;// 继续往上处理:cur = grandfather;parent = cur->_parent;
}

 2.2.2.2变色(叔叔节点为红色)(简单总结版):

判断父亲叔叔方位,叔叔为红,父亲叔叔变黑,爷爷变红继续向上走。

2.2.3.1 左单旋+变色(叔叔节点为黑色或者不存在):

注:这里是由于要进行不同方向的那四种旋转我们才分孩子连接的是父亲的左还是右。

我们首先要想什么时候会左单旋然后变色呢?(首先保持好它的平衡性,故还要旋转变平衡,最后保证节点颜色规则。)  因此左单旋肯定是右边高了,而根据标题就可以知道此时叔叔节点是黑色,但是它是不是第一次插入就黑色了呢?肯定不可能,下面看一张图解释一下:

但是当叔叔不存在时候(虽然也是黑色)但是它只能是新插入的节点而不是向上调整才会出现:

这样我们就明白了把。因此接下来如果要进行左旋故父亲肯定是爷爷的右,孩子也是父亲的右(无论叔叔存在还是存在为黑都一样当黑色处理进行左旋。) 

故我们要先保持它的平衡(右边高了)(利用左旋(对g)):

①首先是叔叔为空(黑):

这样才能保持平衡后,还符合颜色规则。 

②其次是叔叔为存在,黑(就是由最底下插入向上调整时候出现的):

这样我们左单旋的所有情况就完了。

代码实现:

//又分两种情况:孩子插入的是左还是右:
if (cur == parent->_right) {RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;
}

 2.2.3.2左单旋+变色(叔叔节点为黑色或者不存在)(简单总结版):

父亲连接爷爷右,孩子连接父亲右,叔叔存在且黑色(不存在),进行左旋,爷爷变红,父亲变黑。

2.2.4.1 右单旋+变色(叔叔节点为黑色或者不存在):

注:这里是由于要进行不同方向的那四种旋转我们才分孩子连接的是父亲的左还是右。

这里其实就和单旋一样(叔叔存在黑色或者不存在),但是此时就是父亲连接爷爷的左,孩子连接父亲左了。

下面就分情况画图简单看一下吧:

①首先是叔叔为空(黑):

②其次是叔叔为存在,黑(就是由最底下插入向上调整时候出现的):

代码实现:

//又分两种情况:孩子插入的是左还是右:
if (cur == parent->_left) {RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;
}

2.2.4.2 右单旋+变色(叔叔节点为黑色或者不存在)(简单总结版):

父亲连接爷爷左,孩子连接父亲左,叔叔存在且黑色(不存在),进行旋右,爷爷变红,父亲变黑。

2.2.5.1 左右双旋+变色(叔叔节点为黑色或者不存在):

注:这里是由于要进行不同方向的那四种旋转我们才分孩子连接的是父亲的左还是右。

首先我们要知道为什么会出现左右双旋?个人理解:它是右旋样子下孩子插入在父亲右边才会形成的,故此时我们还要分叔叔节点为存在为黑色以及不存在情况进行画图分析。

先说一下它的情况吧:父亲连节爷爷的左边,孩子连接父亲的右边。

①首先是叔叔为空(黑):

对于叔叔是空只能是一开始第一次插入就这样出现的(上面也分析了),下面展示一下它插入并完成旋转和变色的图:

此时我们可以看出进行双旋后把孩子变黑,爷爷变红了。 

②其次是叔叔为存在,黑(就是由最底下插入向上调整时候出现的):

还是老样子叔叔为黑,则孩子节点一定是向上调整由黑变红来的,展示一下:

同理也是孩子变黑,爷爷变红,才能符合既平衡又符合黑色相同规则。 

代码实现:

RotateLR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;

2.2.5.2 左右双旋+变色(叔叔节点为黑色或者不存在)(简单总结版):

父亲连接爷爷的左,孩子连接父亲的右,叔叔为黑或者不存在,此时爷爷变红,孩子变黑。

2.2.6.1右左双旋+变色(叔叔节点为黑色或者不存在):

其实此时的右左双旋和上面的左右双旋相似,只不过是父亲连接了爷爷的右,而孩子连接了父亲的左而已,下面就不过多重复了,画图看一下:

①首先是叔叔为空(黑):

②其次是叔叔为存在,黑(就是由最底下插入向上调整时候出现的):

代码实现:

else {RotateRL(grandfather);cur->_col = BLACK;grandfather->_col = RED;
}

 2.2.6.2右左双旋+变色(叔叔节点为黑色或者不存在)(简单总结版):

父亲连接爷爷的右,孩子连接父亲的左,叔叔为黑或者不存在,此时爷爷变红,孩子变黑。

 2.3红黑树的查找:

这里遵循avl的查找只查找pair的first(根据)而不管颜色故直接用它的查找就行。

代码实现:

 Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;}

2.4红黑树的验证: 

这时候我们就要根据红黑树的四大原则了,但是这里我们只用到了三个:

①根节点为空就是不为空必须是黑色。

②每个节点(这里认为的是根节点起,到空的每条支路的黑色节点数相同)。

③红色节点的孩子一定是黑色节点,但是这里如果这么找,还要判断孩子存不存在然后看颜色,因此我们可以倒着来即找到一个节点是红色,则它的父亲不能是红色(即红色节点不相连)。

黑色节点相同的话,我们可以先往最左或者最右遍历至空,找到一条路径的黑色节点个数作为标准,然后利用递归到空记录blackcount与它比较发现不等就false,红色不相连:遍历途中,发现红色就看父亲颜色,如果为红色就false。

代码展示:

 bool is_rbtree() {int count = 0;if (_root == nullptr) return true;if (_root->_col == RED) return false;//根节点存在就为黑Node* cur = _root;while (cur) {if (cur->_col == BLACK) count++;cur = cur->_left;}return check(_root, count, 0);}bool check(Node* root, int reference, int blackcount) {//查找树中要满足黑色相同以及红的节点只能连两个黑的(转化成红的节点父亲不能是红的):这里只有都满足才返回true,故可以判断错就返falseif (root == nullptr) {//检查每条支路黑色节点数量相同if (blackcount != reference) {cout << "发现黑色节点不等的支路" << endl;return false;}else return true;}if (root->_col == RED && root->_parent->_col == RED) {cout << "发现连续的红色节点" << endl;//不能有连续的红色节点return false;}if (root->_col == BLACK) blackcount++;return check(root->_left, reference, blackcount) && check(root->_right, reference, blackcount);
}

2.5红黑树的删除:

这里和上次的avl树一样采取的是替换制删除,可以根据上篇avl树的删除来仿写,但是就是把平衡因子换成了红黑色的颜色而已。 

三·代码总结: 

#pragma once
#include<iostream>
using namespace std;
enum Colour
{RED,BLACK
};template<class K, class V>
struct RBTreeNode
{pair<K, V> _kv;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Colour _col;RBTreeNode(const pair<K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr){}
};
template<class K, class V>
class RBTree {using Node = RBTreeNode<K, V>;
public:bool insert(const pair<K, V>& kv) {//先按照avl树插入节点,然后最后判断是否旋转来修改颜色//第一次插入要保证根节点为黑色:if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);cur->_col = RED;if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//调整颜色等:(关键看叔叔):while (parent && parent->_col == RED) {//父亲为黑色则不用再次向上调整Node* grandfather = parent->_parent;//爷爷节点一定存在(当父亲节点为红)一定为黑:要么继续调整要么为根节点最后改黑//下面分两种大情况分别是父亲为爷爷的left和right:if (parent == grandfather->_left) {//孩子插入后左高///关键看叔叔节点的情况://叔叔存在且为红:Node* uncle = grandfather->_right;if (uncle && uncle->_col == RED) {parent->_col = uncle->_col = BLACK;grandfather->_col = RED;// 继续往上处理:cur = grandfather;parent = cur->_parent;}//叔叔不存在或者为黑;else {//又分两种情况:孩子插入的是左还是右:if (cur == parent->_left) {RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else {RotateLR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}}else {//孩子插入后右高//叔叔存在且为红:Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED) {parent->_col = uncle->_col = BLACK;grandfather->_col = RED;// 继续往上处理:cur = grandfather;parent = cur->_parent;}//叔叔不存在或者为黑;else {//又分两种情况:孩子插入的是左还是右:if (cur == parent->_right) {RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else {RotateRL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}}}_root->_col = BLACK;//如果到头爷爷原来是黑的被改成了红且是根节点故改回黑return true;}Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;}bool is_rbtree() {int count = 0;if (_root == nullptr) return true;if (_root->_col == RED) return false;//根节点存在就为黑Node* cur = _root;while (cur) {if (cur->_col == BLACK) count++;cur = cur->_left;}return check(_root, count, 0);}int treeheight() {return _treeheight(_root);}int size() {return _size(_root);}void InOrder(){_InOrder(_root);cout << endl;}private:void RotateL(Node* parent) {//左旋Node* subr = parent->_right;Node* subrl = subr->_left;//处理sublr:parent->_right = subrl;if (subrl) subrl->_parent = parent;//sublr为空不能访问Node* pp = parent->_parent;//保存parent的父节点指针//调节新旧“parent”位置:subr->_left = parent;parent->_parent = subr;if (pp == nullptr) {_root = subr;subr->_parent = nullptr;}else {if (parent == pp->_left) pp->_left = subr;else pp->_right = subr;subr->_parent = pp;}}void RotateR(Node* parent) {//右旋Node* subl = parent->_left;Node* sublr = subl->_right;parent->_left = sublr;if (sublr) sublr->_parent = parent;Node* pp = parent->_parent;subl->_right = parent;parent->_parent = subl;if (pp == nullptr) {_root = subl;subl->_parent = nullptr;}else {if (parent == pp->_left) pp->_left = subl;else pp->_right = subl;subl->_parent = pp;}}void	RotateLR(Node* parent) {//左右双旋Node* subl = parent->_left;Node* sublr = subl->_right;RotateL(subl);RotateR(parent);}void RotateRL(Node* parent) {//右左双旋Node* subr = parent->_right;Node* subrl = subr->_left;RotateR(subr);RotateL(parent);}bool check(Node* root, int reference, int blackcount) {//查找树中要满足黑色相同以及红的节点只能连两个黑的(转化成红的节点父亲不能是红的):这里只有都满足才返回true,故可以判断错就返falseif (root == nullptr) {//检查每条支路黑色节点数量相同if (blackcount != reference) {cout << "发现黑色节点不等的支路" << endl;return false;}else return true;}if (root->_col == RED && root->_parent->_col == RED) {cout << "发现连续的红色节点" << endl;//不能有连续的红色节点return false;}if (root->_col == BLACK) blackcount++;return check(root->_left, reference, blackcount) && check(root->_right, reference, blackcount);}int _treeheight(Node* root) {if (root == nullptr)  return 0;int leftheight = _treeheight(root->_left);int rightheight = _treeheight(root->_right);return leftheight > rightheight ? leftheight + 1 : rightheight + 1;}int _size(Node* root) {if (root == nullptr) return 0;return _size(root->_left) + _size(root->_right) + 1;}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_InOrder(root->_right);}Node* _root=nullptr;};

测试用例:

#define _CRT_SECURE_NO_WARNINGS
#include"rbtree.h"int main() {RBTree<int, int> t;// 常规的测试用例//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };// 特殊的带有双旋场景的测试用例int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };for (auto e : a){t.insert({ e, e });}t.InOrder();cout << t.is_rbtree() << endl;cout <<"树的节点大小:"<< t.size() << endl;cout <<" 树的高度:"<< t.treeheight() << endl;}

四·红黑树创建总结(仅个人理解): 

首先的话,我们来谈一谈插入吧:这里可以这么理解:插入就按照二插搜索树插入,然后就是接下来要保证平衡和颜色了,我们插入的红色如果发现父亲是黑色就结束,如果红色,我们三步走:

第一步:判断父亲为爷爷的左还是右。

第二步:看叔叔存在为黑(或者不存在)还是为红。

第三步:看孩子连接父亲的左还是右。

下面画图帮助理解一下:

这里我们可能会说为什么只有叔叔是红色,才会孩子变爷爷向上调整,叔叔是其他就不用?因为当叔叔是其他的时候就会旋转,此时最顶上就是黑色,而旋转带来的改变犹如上调,故可以类似于做到了上调操作。 

本篇结束:希望对每一位读者通过此篇文章对有关红黑树的认识能有所增加,哪怕一丢丢,也更能体现这篇文章存在的价值,感谢各位的用心阅读以及支持!

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

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

相关文章

如意控物联网项目(二)-ML307R模组软件调试之MQTT+硬件接口调试笔记

目录 概要 1、 操作系统----RTOS kernel CMSIS-RTOS2 2、 程序API文档 3、 MQTT调试记录-2024年10月9日 4、 ML307_APP_DEMO_SDK使用指南 5、 MQTT登录onenet平台成功 6、 ML307R链接onenet平台成功-接收数据成功 7、 timer定时器调试 8、 操作系统--OS程序学习 1. 事件…

【实战指南】Vue.js 介绍组件数据绑定路由构建高效前端应用

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

G1 GAN生成MNIST手写数字图像

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 G1 GAN生成MNIST手写数字图像 1. 生成对抗网络 (GAN) 简介 生成对抗网络 (GAN) 是一种通过“对抗性”学习生成数据的深度学习模型&#xff0c;通常用于生成…

SQL Injection | SQL 注入概述

关注这个漏洞的其他相关笔记&#xff1a;SQL 注入漏洞 - 学习手册-CSDN博客 0x01&#xff1a;SQL 注入漏洞介绍 SQL 注入就是指 Web 应用程序对用户输入数据的合法性没有判断&#xff0c;前端传入后端的参数是可控的&#xff0c;并且参数会带入到数据库中执行&#xff0c;导致…

CCS字体、字号更改+CCS下载官方链接

Step1、 按照图示箭头操作 step2 Step3 点击确定&#xff0c;点击Apply(应用)&#xff0c;点击Apply and close(应用和关闭) 4、历代版本下载链接 CCS下载&#xff1a;官方链接https://www.ti.com/tool/CCSTUDIO The last but not least 如果成功的解决了你的问题&#x…

MEMC功能详解

文章目录 MEMC的工作原理&#xff1a;优点&#xff1a;缺点&#xff1a;适用场景&#xff1a;1. Deblur&#xff08;去模糊&#xff09;2. Dejudder&#xff08;去抖动&#xff09;总结两者区别&#xff1a; MEMC&#xff08;Motion Estimation and Motion Compensation&#x…

【开源免费】基于SpringBoot+Vue.JS房屋租赁系统(JAVA毕业设计)

本文项目编号 T 020 &#xff0c;文末自助获取源码 \color{red}{T020&#xff0c;文末自助获取源码} T020&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

编码方式知识整理【ASCII、Unicode和UTF-8】

编码方式 一、ASCII编码二、Unicode 编码三、UTF-8编码四、GB2312编码五、GBK编码 计算机中对数据的存储为二进制形式&#xff0c;但采用什么样的编码方式存储&#xff0c;效率更高。主要编码方式有 ASCII、Unicode、UTF-8等。 英文一般为1个字节&#xff0c;汉字一般为3个字节…

代码复现(五):GCPANet

文章目录 net.py1.class Bottleneck&#xff1a;残差块2.class ResNet&#xff1a;特征提取3.class SRM&#xff1a;SR模块4.class FAM&#xff1a;FIA模块5.class CA&#xff1a;GCF模块6.class SA&#xff1a;HA模块7.class GCPANet&#xff1a;网络架构 train.pytest.py 论文…

【数学二】一元函数积分学-定积分的应用-平面图形面积、旋转体体积、函数的平均值、平面曲线的弧长、旋转曲面面积

考试要求 1、理解原函数的概念&#xff0c;理解不定积分和定积分的概念. 2、掌握不定积分的基本公式&#xff0c;掌握不定积分和定积分的性质及定积分中值定理&#xff0c;掌握换元积分法与分部积分法. 3、会求有理函数、三角函数有理式和简单无理函数的积分. 4、理解积分上限…

进程与线程的区别

1.进程的简单了解 进程是计算机中程序在某个数据集合上的一次运行活动&#xff0c;是操作系统进行资源分配和调度的基本单位。 从不同角度来看&#xff1a; ● 资源分配角度&#xff1a;进程拥有独立的内存地址空间、系统资源&#xff08;如 CPU 时间、文件描述符等&#xf…

【OD】【E卷】【真题】【100分】光伏场地建设规划(PythonJavajavaScriptC++C)

题目描述 祖国西北部有一片大片荒地&#xff0c;其中零星的分布着一些湖泊&#xff0c;保护区&#xff0c;矿区; 整体上常年光照良好&#xff0c;但是也有一些地区光照不太好。 某电力公司希望在这里建设多个光伏电站&#xff0c;生产清洁能源对每平方公里的土地进行了发电评…

关于测试翻译准确率的相关方法

本文提到的翻译准确率测试指标是BLEU&#xff0c;以及使用Python库-fuzzywuzzy来计算相似度 一、基于BLEU值评估 1.只评估一段话&#xff0c;代码如下 from nltk.translate.bleu_score import sentence_bleu, SmoothingFunction# 机器翻译结果 machine_translation "Ho…

【动手学深度学习】8.3 语言模型(个人向笔记)

下面是语言模型的简介 1. 学习语言模型 使用计数来建模 N元语法&#xff1a;这里的元可以理解为我们之前的时间变量。对于 N 元语法&#xff0c;我们可以把所有长度为 N 的子序列存下来。其中 1 元语法用的很少。这里其实就是算概率的时候我们不往前看所有的概率&#xff0c;…

ACL和NAT

一、ACL 1.概述 访问控制列表Access Control List是由一系列permit或deny语句组成的、有序规则的列表是一个匹配工具&#xff0c;对报文进行匹配和区分 2.ACL应用 匹配流量在traffic-filter中被调用在NAT(Natwork Address Translation)中被调用在路由策略中被调用在防火墙的…

Linux系统:本机(物理主机)访问不了虚拟机中的apache服务问题的解决方案

学习目标&#xff1a; 提示&#xff1a;本文主要讲述-本机(物理主机)访问不了虚拟机中的apache服务情况下的解决方案 Linux系统&#xff1a;Ubuntu 23.04&#xff1b; 文中提到的“本机”&#xff1a;代表&#xff0c;宿主机&#xff0c;物理主机&#xff1b; 首先&#xff0c…

OpenCV高级图形用户界面(14)交互式地选择一个或多个感兴趣区域函数selectROIs()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 允许用户在给定的图像上选择多个 ROI。 该函数创建一个窗口&#xff0c;并允许用户使用鼠标来选择多个 ROI。控制方式&#xff1a;使用空格键或…

【Unity新闻】Unity 6 正式版发布

Unity CEO Matt Bromberg 在今天自豪地宣布&#xff0c;Unity 6 正式发布&#xff01;作为迄今为止最强大和稳定的版本&#xff0c;Unity 6 为游戏和应用开发者提供了大量的新功能和工具&#xff0c;帮助他们加速开发并提升性能。 本次正式版是6.0000.0.23f1&#xff08;LTS&a…

Django学习(三)

Django的设计模式及模板层 传统的MVC&#xff08;例如java&#xff09; Django的MTV 模板层&#xff1a; 模板加载&#xff1a; 代码&#xff1a; views.py def test_html(request):#方案一# from django.template import loader# 1. 使用loader加载模板# t loader.get_…

WIFI实现透传+接线图

单片机通过TX接WIFI模块的RX将设置的AT代码写入WIFI模块&#xff08;连接WIFI调为设备模式&#xff08;有设备&#xff0c;路由&#xff0c;双模等模式&#xff09;&#xff09; WIFI模块将响应信号通过TX通过CH340发给PC的RX 通过STC-ISP或安信可串口调试助手查看响应信息 …