当前位置: 首页 > news >正文

【C++】AVL树和红黑树(插入和测试详解)

文章目录

    • 1、AVL树
      • 1.1 AVL树的插入
      • 1.2 总结与测试AVL树
    • 2、红黑树
      • 2.1 红黑树的插入
      • 2.2 红黑树的测试

了解AVL树是为了了解红黑树,了解红黑树是为了更好的理解set和map。

1、AVL树

AVL树是在二叉搜索树的基础上进行了严格的平衡,能做到平衡的关键是通过平衡因子以及旋转。
AVL树有以下特性:

  1. 任何根的左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)。
  2. 其中平衡因子是用右子树高度减去左子树高度。
  3. 任何子树都是AVL树。

在这里插入图片描述

下面实现的AVL树还是KV结构的。

AVL树节点定义

#include <iostream>
#include <assert.h>
using namespace std;template<class K, class V>
struct AVLTreeNode
{//三叉链结构方便访问父节点struct AVLTreeNode<K, V>* _left;struct AVLTreeNode<K, V>* _right;struct AVLTreeNode<K, V>* _parent;pair<K, V> _kv; //键值对 里面存储key和valueint _bf; //平衡因子AVLTreeNode(const pair<K, V>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_bf(0)
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:private:Node* root = nullptr;
};

1.1 AVL树的插入

1、AVL树的插入首先一开始和二叉搜索树的插入一样,先确定插入的位置,再和父节点链接。

2、插入完后,可能会破坏AVL树结构,所以要判断平衡因子。
插入新结点后,平衡因子会出现三种情况。
在这里插入图片描述

3、当平衡因子出现了-2或2的情况,这个时候就需要对parent进行旋转。
旋转有以下情况。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

bool insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* cur = _root;Node* parent = _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);//只能用kv值来确定parent和cur的指向if (parent->_kv.first < kv.first){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//判断平衡因子while (parent){if (parent->_left == cur){//根节点左边插入节点,根的平衡因子-1parent->_bf--;}else{//根节点右边插入节点,根的平衡因子+1parent->_bf++;}//说明之前是-1或1,变为平衡if (parent->_bf == 0){break;}else if (parent->_bf == 1 || parent->_bf == -1){//下面子树高度差也影响了上面的根结点,所以需要向上调整cur = parent;parent = cur->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){//这个时候就需要旋转,使得树平衡if (parent->_bf == -2 && cur->_bf == -1){//这是右旋转的情况RotateR(parent);}else if (parent->_bf == 2 && cur->_bf == 1){RotateL(parent);}else if (parent->_bf == -2 && cur->_bf == 1){RotateLR(parent);}else if (parent->_bf == 2 && cur->_bf == -1){RotateRL(parent);}else{assert(false);}//旋转完后,结构平衡,退出break;}else{//如果平衡因子出现其它情况,说明错了assert(false);}}//whilereturn true;}

旋转:

	//右旋转void RotateR(Node* parent){//从下到上依次修改Node* sub = parent->_left;Node* subR = sub->_right;//先改变最下面的subR结点parent->_left = subR;if (subR){subR->_parent = parent;}//再改变parent结点sub->_right = parent;Node* ppnode = parent->_parent;parent->_parent = sub;//最后改变sub结点if (ppnode == nullptr){_root = sub;_root->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = sub;}else{ppnode->_right = sub;}sub->_parent = ppnode;}parent->_bf = sub->_bf = 0;}//左旋和右旋类似void RotateL(Node* parent){Node* sub = parent->_right;Node* subL = sub->_left;parent->_right = subL;if (subL){subL->_parent = parent;}sub->_left = parent;Node* ppnode = parent->_parent;parent->_parent = sub;if (ppnode == nullptr){_root = sub;_root->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = sub;}else{ppnode->_right = sub;}sub->_parent = ppnode;}parent->_bf = sub->_bf = 0;}void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;//保存subLR的平衡因子,为了知道从subLR哪边插入int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == -1) // subLR左子树新增{subL->_bf = 0;parent->_bf = 1;subLR->_bf = 0;}else if (bf == 1) // subLR右子树新增{parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else if (bf == 0) // subLR自己就是新增{parent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}else{assert(false);}}//和上面类似void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == -1) // subRL左子树新增{subR->_bf = 1;parent->_bf = 0;subRL->_bf = 0;}else if (bf == 1) // subRL右子树新增{parent->_bf = -1;subR->_bf = 0;subRL->_bf = 0;}else if (bf == 0) // subRL自己就是新增{parent->_bf = 0;subR->_bf = 0;subRL->_bf = 0;}else{assert(false);}}

可能会有的问题解释(以下是自己的理解):

1、如何想到旋转的情况?
其实从所有情况看就这两个情况以及他们的翻转,记住它们两个就好了。
在这里插入图片描述

2、如何看左右旋?
拿上图举例,左边是一个右旋能平衡的场景,只需要将最高的结点往右放就行。
右边是一个双选的场景,先将中间结点左旋,就成了图左边的场景,再右旋就行。

1.2 总结与测试AVL树

AVL树重点关注的是其平衡因子和选择如何使得AVL树平衡,通过插入了解就足够了。
下面是如何测试结果是AVL树:
1、通过每个结点的左右子树的高度判断平衡因子是否符合要求。
2、通过小和大的测试用例测试是不是AVL树

#pragma once
#include <iostream>
#include <assert.h>
using namespace std;template<class K, class V>
struct AVLTreeNode
{struct AVLTreeNode<K, V>* _left;struct AVLTreeNode<K, V>* _right;struct AVLTreeNode<K, V>* _parent;pair<K, V> _kv;int _bf;AVLTreeNode(const pair<K, V>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_bf(0){}
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:bool insert(const pair<K, V>& kv){}void RotateR(Node* parent){}void RotateL(Node* parent){}void RotateLR(Node* parent){}void RotateRL(Node* parent){}int Height(Node* root){if (root == nullptr){return 0;}int leftHight = Height(root->_left);int rightHight = Height(root->_right);return leftHight > rightHight ? leftHight + 1 : rightHight + 1;}bool IsBalanceTree(){return  _IsBalanceTree(_root);}bool _IsBalanceTree(Node* parent){if (parent == nullptr){return true;}int leftHight = Height(parent->_left);int rightHight = Height(parent->_right);int diff = rightHight - leftHight;if (diff != parent->_bf || (diff > 1 || diff < -1)){cout << "有错" << endl;return false;}return _IsBalanceTree(parent->_left) && _IsBalanceTree(parent->_right);}void Inorder(){_Inorder(_root);}void _Inorder(Node* root){if (root == nullptr)return;_Inorder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_Inorder(root->_right);}
private:Node* _root = nullptr;
};//出错用小用例调
void test1()
{int arr[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };int arr2[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };AVLTree<int, int> t;for (auto& e : arr){if(e == 18){	//调试断点int a = 0;}t.insert(make_pair(e, e));t.IsBalanceTree();}t.Inorder();
}//没错用多数据看看能不能过
#include <cstdlib>
void test2()
{srand(time(NULL));AVLTree<int, int> t;for (int i = 0; i < 100000; ++i){int num = rand() % 10000;t.insert(make_pair(num, num));}t.IsBalanceTree();
}

2、红黑树

AVL树因为其严格的平衡导致它因为大量的旋转导致效率相较红黑树低。

红黑树不要求严格平衡,它为每个结点加上颜色区分,使得它趋向于平衡。它有着以下规定。

  1. 根节点必须是黑色。
  2. 根节点颜色要么是红色,要么是黑色。
  3. 红色结点不能连续。(也就是如果一个结点是红的,其两个子结点都是黑的)
  4. 每条路径下的黑色结点树要一样。
  5. 叶子结点都是黑色结点(这里叶子结点代表NULL结点)

在这里插入图片描述

可能概念理解起来很抽象,我们通过代码一步步来。

首先搭建红黑树的框架。
大致和AVL树一样,只不过没有平衡因子,换成了颜色。

#include <iostream>
#include <assert.h>
using namespace std;enum Color { RED, BLACK };template<class K, class V>
struct RBTreeNode
{struct RBTreeNode<K, V>* _left;struct RBTreeNode<K, V>* _right;struct RBTreeNode<K, V>* _parent;pair<K, V> _kv;Color _col;RBTreeNode(const pair<K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr), _col(BLACK){}
};template<class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public:
private:Node* _root = nullptr;
};

2.1 红黑树的插入

1、首先如果根是空,新建的结点一定是黑色结点。这很好理解。
2、那么如果是后面创建的结点,是黑色还是红色呢?
 2.1 如果是黑色结点,那么想象一下,给某个路径添加一个黑色结点,使得这个路径的黑结点数量和其他路径不同,直接导致整个树不满足红黑树条件,直接破坏整个红黑树。
 2.2 如果是红色结点,最差只会出现两个红色结点相连的情况,只影响这个子树。

 所以综上选择影响最少的,选择创建红色结点。
3、插入前面和搜索树一样,得先确认插入的位置,以及和父节点链接。
4、调整红黑树在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
除此以外当然还有翻转的另一类情况。

bool insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;return true;}Node* cur = _root;Node* parent = _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 < cur->_kv.first){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//调整//parent为红,代表插入的子节点也为红,需要调整。while (parent && parent->_col == RED){Node* grandparent = parent->_parent;//首先是第一类父亲结点在祖父结点左边,叔叔结点在右边的一类情况。if (parent == grandparent->_left){Node* uncle = grandparent->_right;if (uncle && uncle->_col == RED){//第一种情况 叔叔结点存在且为红色parent->_col = BLACK;uncle->_col = BLACK;grandparent->_col = RED;//向上调整,根节点的情况可以跑完整个调整,再设置_root->_col = BLACK;cur = grandparent;parent = cur->_parent;}else{//这一类是叔叔结点不存在以及存在为黑色//因为处理方法都是一样的,所以只要再区分直线型和折线型。if (parent->_right == cur){//折线的情况RotateL(parent);RotateR(grandparent);cur->_col = BLACK;grandparent->_col = RED;}else{//直线的情况RotateR(grandparent);parent->_col = BLACK;grandparent->_col = RED;}break;}}else{//这一类是上面翻转,一样的处理,但注意方向Node* uncle = grandparent->_left;if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;grandparent->_col = RED;cur = grandparent;parent = cur->_parent;}else{if (parent->_right == cur){RotateL(grandparent);parent->_col = BLACK;grandparent->_col = RED;}else{RotateR(parent);RotateL(grandparent);cur->_col = BLACK;grandparent->_col = RED;}break;}}}//最后确保根节点为黑。_root->_col = BLACK;return true;}//剩下左右旋转的代码和AVL中的一样。

如果记忆红黑树的情况?(个人方式)
首先要记得红黑树的特性,根一定是黑结点,想清楚为什么插入要插红结点,这样能更情况红黑树的特性。

像情况一的推理一样,先插入黑色的根节点,再插入红结点,层序插入直到出现问题,此时面对第一个情况,叔叔结点存在并且为红色。

然后考虑叔叔结点为黑和不存在的情况,因为要旋转,再根据AVL树中记忆的两个情况,推出除了直线型情况,还有折线型情况。

2.2 红黑树的测试

在测试中,需要判断的

1. 根要为黑结点。
2.判断父子结点不能都为红
3.确保每条路径的黑结点数相同(这里通过先计算一条路径的黑结点数,再和每一条路径比对)

bool Check(Node* proot, int count, int ref){if (proot == nullptr){//检查黑结点if (count != ref){cout << "出现路径黑结点树不同" << endl;return false;}return true;}Node* parent = proot->_parent;if (parent && (parent->_col == RED && proot->_col == RED)){cout << "出现了连续的红结点" << endl;return false;}if (proot->_col == BLACK){count += 1;}return Check(proot->_left, count, ref) && Check(proot->_right, count, ref);}bool IsRBTree(){if (_root == nullptr){return true;}if (RED == _root->_col){cout << "根节点不能为红色" << endl;return false;}int ref = 0;Node* checkblack = _root;while (checkblack){if (BLACK == checkblack->_col){ref++;}checkblack = checkblack->_left;}return Check(_root, 0, ref);}

本节完~

相关文章:

【C++】AVL树和红黑树(插入和测试详解)

文章目录1、AVL树1.1 AVL树的插入1.2 总结与测试AVL树2、红黑树2.1 红黑树的插入2.2 红黑树的测试了解AVL树是为了了解红黑树&#xff0c;了解红黑树是为了更好的理解set和map。 1、AVL树 AVL树是在二叉搜索树的基础上进行了严格的平衡&#xff0c;能做到平衡的关键是通过平衡…...

Centos7 安装 Mysql 8.0.32,详细完整教程(好文章!!)

mysql5.7的安装方式参考之前的文章&#xff1a; centos7 安装 Mysql 5.7.27&#xff0c;详细完整教程&#xff08;好文章&#xff01;&#xff01;&#xff09;_HD243608836的博客-CSDN博客 一、检查mysql版本冲突 先检查是否已经存在mysql&#xff0c;若存在卸载&#xff0…...

Apache Beanutils为什么被禁止使用?

收录于热门专栏Java基础教程系列&#xff08;进阶篇&#xff09; 在实际的项目开发中&#xff0c;对象间赋值普遍存在&#xff0c;随着双十一、秒杀等电商过程愈加复杂&#xff0c;数据量也在不断攀升&#xff0c;效率问题&#xff0c;浮出水面。 问&#xff1a;如果是你来写…...

sql server执行md5加密的时候,字符串前带N和不带N的结果是不一样的

最近因为项目的需要&#xff0c;报表中需要对数据进行MD5加密&#xff0c;结果报表系统得出来的sql语句&#xff0c;字符串前都自动带了N&#xff0c;执行时&#xff0c;发现得到的结果跟在数据库中执行的sql&#xff08;字符串不带N&#xff09;得的值不一样&#xff0c;最后自…...

01Python编译器和编辑器下载

Python下载 通过python官网下载:https://www.python.org/因为python官网的服务器在国外,我们可以通过腾讯软件中心下载https://pc.qq.com/search.html#!keyword=python 腾讯软件中心下载请使用普通下载,其他什么下载会自动帮你下个电脑管家(没必要) python简单描述 python…...

CHAPTER 5 自动发现、自动注册、分布式监控、SNMP监控

自动发现与自动注册5.1 自动发现与自动注册5.1.1 简介5.1.2 两种模式5.2 自动发现--被动模式5.3 自动注册--主动模式5.4 分布式监控5.4.1 介绍5.4.2 配置zabbix proxy5.5 SNMP监控5.5.1 使用范围5.5.2 安装snmp程序5.5.3 配置snmp程序5.5.4 测试snmp5.5.5 在web界面进行配置5.1…...

P5311 [Ynoi2011] 成都七中

题目描述 给你一棵 nnn 个节点的树&#xff0c;每个节点有一种颜色&#xff0c;有 mmm 次查询操作。 查询操作给定参数 lrxl\ r\ xl r x&#xff0c;需输出&#xff1a; 将树中编号在 [l,r][l,r][l,r] 内的所有节点保留&#xff0c;xxx 所在连通块中颜色种类数。 每次查询操…...

Python 日期和时间格式

Python 程序能用很多方式处理日期和时间&#xff0c;转换日期格式是一个常见的功能。Python 提供了一个 time 和 calendar 模块可以用于格式化日期和时间。时间间隔是以秒为单位的浮点小数。每个时间戳都以自从1970年1月1日午夜&#xff08;历元&#xff09;经过了多长时间来表…...

电脑和手机的软件推荐

安卓软件 jota text 记事本 x浏览器 &#xff08;支持禁js&#xff0c;支持嗅探 视频 音频&#xff09; __ 空缺 暂未能发现好用的office软件 snapseed图片调整 可谓手机界的photoshop vidtrim视频剪辑 librera reader &#xff08;无广告 电子书软件 但是发音很差 lithum或者…...

酸回收树脂的应用

酸洗废水 在轧钢、金属表面处理、电子元件制造等过程中需要清除钢材表面氧化铁皮而使用酸进行酸洗&#xff0c;酸洗过程中会产生废酸液和酸洗废水。 这些废酸产量大、酸度高&#xff0c;而且由于酸洗废水来自钢铁和金属表面处理的清洗水&#xff0c;水中含有多种重金属离子&am…...

windows上配置IIS全过程

文章目录1️⃣ 配置IIS1.1 从开始打开服务器管理1.2 添加角色和功能1.3 添加角色和功能向导1.4 按照如下步骤选择2️⃣ 问题&#xff1a;缺少源文件解决方案优质资源分享作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/1…...

软考高级信息系统项目管理师系列之十三:项目成本管理

软考高级信息系统项目管理师系列之十三:项目成本管理 一、成本管理领域输入、输出、工具和技术表二、成本管理基础知识点1.成本类型2.应急储备和管理储备3.成本基准三、项目成本管理过程1.项目成本管理的过程2.成本管理计划3.项目成本估算的主要步骤4.活动成本估算5.项目预算6…...

HIVE 基础(一)

目录 启动hive 方式一 方式二 修改hdfs上给定文件执行的读写权限 创建数据库 查看数据库 查看数据库详细信息 查看当前数据库 创建表 查看建表语句 查看表信息 删除表 添加数据 查看表数据 删除数据库 强制删除数据库 启动hive 方式一 [roothadoop1 ~]# hive 方…...

《狂飙》壁纸太帅,Python自动切换太酷(8)

小朋友们好&#xff0c;大朋友们好&#xff01;我是猫妹&#xff01;要说最近什么电视剧最火&#xff1f;非《狂飙》莫属。《狂飙》剧名来自毛主席诗词“国际悲歌歌一曲&#xff0c;狂飙为我从天落”。导演借用“狂飙”二字来比喻剧中的扫黑除恶大风暴。据了解&#xff0c;《狂…...

博客排名的影响是什么? 说明优点、注册方法和推荐网站

如果您经营博客&#xff0c;您是否在博客排名网站上注册&#xff1f;博客排名网站是以排名格式介绍各种注册博客的网站。如果您注册博客&#xff0c;您将有更多机会被人们看到&#xff0c;并且可以期望增加访问权限。对于那些刚刚打开博客并担心访问量不会轻易增加的人来说&…...

全流程GMS地下水数值模拟技能培养及溶质运移反应问题深度解析实践技术

本次综合前期多次学习的效果及重点关注环节&#xff0c;系统性呈现地下水数值模拟软件GMS建模方法同时&#xff0c;建立与实践项目过程中的重点问题相融合&#xff0c;在教学中不仅强调学习三维地质结构建模、水文地质模型概化、边界条件设定、参数反演和模型校核等关键环节&am…...

【软件架构设计】SOA/软件架构设计---面向服务的架构(SOA详细解释)

文章目录面向服务的架构SOA 概述1. 服务的基本结构2.SOA 设计原则3. 服务构件与传统构件SOA 的关键技术1. UDDI2.WSDL3.SOAP4.RESTSOA 的实现方法1.Web Service2. 服务注册表3. 企业服务总线微服务1.微服务的优势2. 微服务面临的挑战3.微服务与 SOA面向服务的架构 迄今为止&am…...

erupt框架Ueditor富文本编辑器图片上传出现405异常

最近在研究erupt框架(v1.11.2),当字段使用Ueditor富文本编辑器,在图片上传的时候出现405异常,接口不支持POST请求方式: 根据错误提示找到对应的源码,发现Handler方法只支持GET请求,而图片上传的时候是以POST方式发起请求的; 此时需要修改源码,用自定义的类覆盖jar包中同名的…...

FILE文件操作

文件指针 每个被使用的文件都在内存中开辟了一个相应的文件信息区&#xff0c;用来存放文件的相关信息&#xff08;如文件的名 字&#xff0c;文件状态及文件当前的位置等&#xff09;。这些信息是保存在一个结构体变量中的。该结构体类型是有系统 声明的&#xff0c;取名FILE…...

SAP PP工单确认完成(CNF)状态取消方法

这SAP PP工单确认完成&#xff08;CNF&#xff09;状态取消方法SAP PP工单确认完成&#xff08;CNF&#xff09;状态取消方法SAP PP工单确认完成&#xff08;CNF&#xff09;状态取消方法 工单完工后取消了其中的一个报工&#xff0c;然后无法再报工 此时再报工&#xff0c;系…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...