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

【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树

目录

1 -> 红黑树

1.1 -> 红黑树的概念

1.2 -> 红黑树的性质

1.3 -> 红黑树节点的定义

1.4 -> 红黑树的结构

1.5 -> 红黑树的插入操作

1.6 -> 红黑树的验证

1.8 -> 红黑树与AVL树的比较

2 -> 红黑树模拟实现STL中的map与set

2.1 -> 红黑树的迭代器

2.2 -> 改造红黑树

2.3 -> map的模拟实现

2.4 -> set的模拟实现


1 -> 红黑树

1.1 -> 红黑树的概念

红黑树,是一种二叉搜索树,但在每个节点上增加了一个存储位表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。

1.2 -> 红黑树的性质

  1. 每个节点不是红色就是黑色。
  2. 根节点是黑色的。
  3. 如果一个节点是红色的,则它的两个孩子节点是黑色的。
  4. 对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
  5. 每个叶子节点都是黑色的(此处的叶子节点指空节点)。

1.3 -> 红黑树节点的定义

#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
using namespace std;// 节点的颜色
enum Color 
{ RED, BLACK 
};// 红黑树节点的定义
template<class ValueType>
struct RBTreeNode
{RBTreeNode(const ValueType& data = ValueType(),Color color = RED): _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr), _data(data), _color(color){}RBTreeNode<ValueType>* _pLeft;   // 节点的左孩子RBTreeNode<ValueType>* _pRight;  // 节点的右孩子RBTreeNode<ValueType>* _pParent; // 节点的双亲(红黑树需要旋转,为了实现简单给出该字段)ValueType _data; // 节点的值域Color _color;    // 节点的颜色
};

1.4 -> 红黑树的结构

为了后续实现关联式容器更加简单,红黑树的实现中增加一个头节点,因为根节点必须是黑色的,为了与根节点区分开,将头节点给成黑色,并且让头节点的pParent域指向红黑树的根节点,pLeft域指向红黑树中最小的节点,_pRight域指向红黑树中最大的节点。

1.5 -> 红黑树的插入操作

红黑树是在二叉搜索树的基础上加上其平衡限制条件,因此红黑树的插入可以分为两步:

1. 按照二叉搜索树的树规则插入新节点。

template<class ValueType>
struct RBTree
{bool Insert(const ValueType& data){PNode& pRoot = GetRoot();if (nullptr == pRoot){pRoot = new Node(data, BLACK);// 根的双亲为头节点pRoot->_pParent = _pHead;_pHead->_pParent = pRoot;}else{// 1. 按照二叉搜索的树方式插入新节点// 2. 检测新节点插入后,红黑树的性质是否造到破坏,//    若满足直接退出,否则对红黑树进行旋转着色处理}// 根节点的颜色可能被修改,将其改回黑色pRoot->_color = BLACK;_pHead->_pLeft = LeftMost();_pHead->_pRight = RightMost();return true;}
private:PNode& GetRoot(){return _pHead->_pParent;}// 获取红黑树中最小节点,即最左侧节点PNode LeftMost();// 获取红黑树中最大节点,即最右侧节点PNode RightMost();private:PNode _pHead;
}

2. 检测新节点插入后,红黑树的性质是否遭到破坏。

因为新节点的默认颜色为红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树的任何性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三,即不能有连在一起的红色节点,此时需要对红黑树分情况来讨论: 

  • 情况一:cur为红,p为红,g为黑,u存在且为红。

注意:此处看到的树可能是一棵完整的树,也可能是一棵子树。

如果g是根节点,调整完成后,需要将g改为黑色。

如果g是子树,g一定有双亲,且g的双亲如果是红色,就需要继续向上调整。 

cur和p均为红,违反了性质三。

解决方法:将p、u改为黑,g改为红,然后把g当成cur,继续向上调整。 

  • 情况二:cur为红,p为红,g为黑,u不存在/u存在且为黑。

 说明:

  1. 如果u节点不存在,则cur一定是新插入节点,因为如果cur不是新插入节点,则cur和p一定有一个节点的颜色是黑色,就不满足性质4:每条路径黑色节点个数相同。
  2. 如果u节点存在,则其一定是黑色的,那么cur节点原来的颜色一定是黑色的,现在看到其是红色的原因是因为cur的子树在调整的过程中将cur节点的颜色由黑色改成了红色。

p为g的左孩子,cur为p的左孩子,则进行右单旋转。

p为g的右孩子,cur为p的右孩子,则进行左单旋转。

p、g变色——p变黑,g变红。

  • 情况三:cur为红,p为红,g为黑,u不存在/u存在且为黑。

 

p为g的左孩子,cur为p的右孩子,则针对p进行左单旋转。

p为g的右孩子,cur为p的左孩子,则针对p进行右单旋转。

则转换成情况二。

针对每种情况进行相应的处理即可。

bool Insert(const ValueType& data)
{// ...// 新节点插入后,如果其双亲节点的颜色为空色,则违反性质3:不能有连在一起的红色结点while (pParent && RED == pParent->_color){// 注意:grandFather一定存在// 因为pParent存在,且不是黑色节点,则pParent一定不是根,则其一定有双亲PNode grandFather = pParent->_pParent;// 先讨论左侧情况if (pParent == grandFather->_pLeft){PNode unclue = grandFather->_pRight;// 情况三:叔叔节点存在,且为红if (unclue && RED == unclue->_color){pParent->_color = BLACK;unclue->_color = BLACK;grandFather->_color = RED;pCur = grandFather;pParent = pCur->_pParent;}else{// 情况五:叔叔节点不存在,或者叔叔节点存在且为黑if (pCur == pParent->_pRight){_RotateLeft(pParent);swap(pParent, pCur);}// 情况五最后转化成情况四grandFather->_color = RED;pParent->_color = BLACK;_RotateRight(grandFather);}}else{// …}}// ...
}

1.6 -> 红黑树的验证

红黑树的检测分为两步:

  1. 检测其是否满足二叉搜索树(中序遍历是否为有序序列)。
  2. 检测其是否满足红黑树的性质。
bool IsValidRBTree(){PNode pRoot = GetRoot();// 空树也是红黑树if (nullptr == pRoot)return true;// 检测根节点是否满足情况if (BLACK != pRoot->_color){cout << "违反红黑树性质二:根节点必须为黑色" << endl;return false;}// 获取任意一条路径中黑色节点的个数size_t blackCount = 0;PNode pCur = pRoot;while (pCur){if (BLACK == pCur->_color)blackCount++;pCur = pCur->_pLeft;}// 检测是否满足红黑树的性质,k用来记录路径中黑色节点的个数size_t k = 0;return _IsValidRBTree(pRoot, k, blackCount);}bool _IsValidRBTree(PNode pRoot, size_t k, const size_t blackCount){//走到null之后,判断k和black是否相等if (nullptr == pRoot){if (k != blackCount){cout << "违反性质四:每条路径中黑色节点的个数必须相同" << endl;return false;}return true;}// 统计黑色节点的个数if (BLACK == pRoot->_color)k++;// 检测当前节点与其双亲是否都为红色PNode pParent = pRoot->_pParent;if (pParent && RED == pParent->_color && RED == pRoot->_color){cout << "违反性质三:没有连在一起的红色节点" << endl;return false;}return _IsValidRBTree(pRoot->_pLeft, k, blackCount) &&_IsValidRBTree(pRoot->_pRight, k, blackCount);}

1.8 -> 红黑树与AVL树的比较

红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O(n),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以在实际运用中红黑树更多。

2 -> 红黑树模拟实现STL中的map与set

2.1 -> 红黑树的迭代器

迭代器的好处是可以方便遍历,是数据结构的底层实现与用户透明。如果想要给红黑树增加迭代器,需要考虑以下问题:

  • begin()和end()

STL明确规定,begin()与end()代表的是一段前闭后开的区间,而对红黑树进行中序遍历后,可以得到一个有序的序列,因此:begin()可以放在红黑树中最小节点(即最左侧节点)的位置,end()放在最大节点(最右侧节点)的下一个位置,关键是最大节点的下一个位置在哪里呢?能否给成nullptr呢?

答案是行不通的,因为对end()位置的迭代器进行--操作,必须要能找到最后一个元素,此处就不行,因此最好的方式是将end()放在头节点的位置

  • operator++()与operator--() 
// 找迭代器的下一个节点,下一个节点肯定比其大void Increasement(){//分两种情况讨论:_pNode的右子树存在和不存在// 右子树存在if (_pNode->_pRight){// 右子树中最小的节点,即右子树中最左侧节点_pNode = _pNode->_pRight;while (_pNode->_pLeft)_pNode = _pNode->_pLeft;}else{// 右子树不存在,向上查找,直到_pNode != pParent->rightPNode pParent = _pNode->_pParent;while (pParent->_pRight == _pNode){_pNode = pParent;pParent = _pNode->_pParent;}// 特殊情况:根节点没有右子树if (_pNode->_pRight != pParent)_pNode = pParent;}}// 获取迭代器指向节点的前一个节点void Decreasement(){//分三种情况讨论:_pNode 在head的位置,_pNode 左子树存在,_pNode 左子树不存在// 1. _pNode 在head的位置,--应该将_pNode放在红黑树中最大节点的位置if (_pNode->_pParent->_pParent == _pNode && _pNode->_color == RED)_pNode = _pNode->_pRight;else if (_pNode->_pLeft){// 2. _pNode的左子树存在,在左子树中找最大的节点,即左子树中最右侧节点_pNode = _pNode->_pLeft;while (_pNode->_pRight)_pNode = _pNode->_pRight;}else{// _pNode的左子树不存在,只能向上找PNode pParent = _pNode->_pParent;while (_pNode == pParent->_pLeft){_pNode = pParent;pParent = _pNode->_pParent;}_pNode = pParent;}}

2.2 -> 改造红黑树

#pragma once// set ->key
// map ->key/valueenum Colour
{RED,BLACK
};template<class T>
struct RBTreeNode
{RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;T _data;Colour _col;RBTreeNode(const T& data):_left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _col(RED){}
};template<class T>
struct __TreeIterator
{typedef RBTreeNode<T> Node;typedef __TreeIterator<T> Self;Node* _node;__TreeIterator(Node* node):_node(node){}T& operator*(){return _node->_data;}T* operator->(){return &_node->_data;}Self& operator--();Self& operator++(){if (_node->_right){// 下一个就是右子树的最左节点Node* cur = _node->_right;while (cur->_left){cur = cur->_left;}_node = cur;}else{// 左子树 根 右子树// 右为空,找孩子是父亲左的那个祖先Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}
};// set->RBTree<K, K, SetKeyOfT> _t;
// map->RBTree<K, pair<K, T>, MapKeyOfT> _t;
template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<T> Node;
public:typedef __TreeIterator<T> iterator;iterator begin(){Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return iterator(cur);}iterator end(){return iterator(nullptr);}pair<iterator, bool> Insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return make_pair(iterator(_root), true);}Node* parent = nullptr;Node* cur = _root;KeyOfT kot;while (cur){if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else{return make_pair(iterator(cur), false);}}// 新增节点给红色cur = new Node(data);Node* newnode = cur;cur->_col = RED;if (kot(parent->_data) < kot(data)){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}while (parent && parent->_col == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){//     g//   p   u// cNode* 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){// 单旋//     g//   p// cRotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// 双旋//     g//   p//     cRotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}else  // parent == grandfather->_right{//     g//   u   p //          c//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{//     g//   u   p //     c//RotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}}_root->_col = BLACK;return make_pair(iterator(newnode), true);}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;subR->_left = parent;Node* parentParent = parent->_parent;parent->_parent = subR;if (subRL)subRL->_parent = parent;if (_root == parent){_root = subR;subR->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subR;}else{parentParent->_right = subR;}subR->_parent = parentParent;}}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;Node* parentParent = parent->_parent;subL->_right = parent;parent->_parent = subL;if (_root == parent){_root = subL;subL->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subL;}else{parentParent->_right = subL;}subL->_parent = parentParent;}}void InOrder(){_InOrder(_root);cout << endl;}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << " ";_InOrder(root->_right);}// 根节点->当前节点这条路径的黑色节点的数量bool Check(Node* root, int blacknum, const int refVal){if (root == nullptr){//cout << balcknum << endl;if (blacknum != refVal){cout << "存在黑色节点数量不相等的路径" << endl;return false;}return true;}if (root->_col == RED && root->_parent->_col == RED){cout << "有连续的红色节点" << endl;return false;}if (root->_col == BLACK){++blacknum;}return Check(root->_left, blacknum, refVal)&& Check(root->_right, blacknum, refVal);}bool IsBalance(){if (_root == nullptr)return true;if (_root->_col == RED)return false;//参考值int refVal = 0;Node* cur = _root;while (cur){if (cur->_col == BLACK){++refVal;}cur = cur->_left;}int blacknum = 0;return Check(_root, blacknum, refVal);}int Height(){return _Height(_root);}int _Height(Node* root){if (root == nullptr)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}size_t Size(){return _Size(_root);}size_t _Size(Node* root){if (root == NULL)return 0;return _Size(root->_left)+ _Size(root->_right) + 1;}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 NULL;}private:Node* _root = nullptr;
};

2.3 -> map的模拟实现

map的底层结构就是红黑树,因此在map中直接封装一棵红黑树,然后将其接口包装下即可。

#pragma once
#include"RBTree.h"namespace fyd
{template<class K, class V>class map{public:struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};// 对类模板取内嵌类型,加typename告诉编译器这里是类型typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}V& operator[](const K& key){pair<iterator, bool> ret = insert(make_pair(key, V()));return ret.first->second;}pair<iterator, bool> insert(const pair<K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<K, V>, MapKeyOfT> _t;};
}

2.4 -> set的模拟实现

set的底层为红黑树,因此只需在set内部封装一棵红黑树,即可将该容器实现出来。

#pragma once
#include"RBTree.h"namespace fyd
{template<class K>class set{public:struct SetKeyOfT{const K& operator()(const K& key){return key;}};typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}pair<iterator, bool> insert(const K& key){return _t.Insert(key);}private:RBTree<K, K, SetKeyOfT> _t;};
}

感谢各位大佬支持!!!

互三啦!!!

相关文章:

【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树

目录 1 -> 红黑树 1.1 -> 红黑树的概念 1.2 -> 红黑树的性质 1.3 -> 红黑树节点的定义 1.4 -> 红黑树的结构 1.5 -> 红黑树的插入操作 1.6 -> 红黑树的验证 1.8 -> 红黑树与AVL树的比较 2 -> 红黑树模拟实现STL中的map与set 2.1 -> 红…...

MySQL DDL

数据库 1 创建数据库 CREATE DATABASE 数据库名 CREATE DATABASE IF NOT EXISTS 数据库名;&#xff08;判断是否存在) CREATE DATABASE 数据库名 CHARACTER SET 字符 2 查看数据库 SHOW DATABASES; 查看某个数据库的信息 SHOW CAEATE DATABASE 数据库名 3 修改数据库 …...

从模型到应用:李彦宏解读AI时代的新趋势与挑战

如何理解李彦宏说的“不要卷模型&#xff0c;要卷应用” 开源项目的机遇与挑战 7月4日&#xff0c;2024世界人工智能大会暨人工智能全球治理高级别会议在上海世博中心举办。在产业发展主论坛上&#xff0c;百度创始人、董事长兼首席执行官李彦宏呼吁&#xff1a;“大家不要卷…...

C++ STL 随机数用法介绍

目录 一&#xff1a;C语言中的随机数 二&#xff1a;C中的随机数 1. 生成随机数的例子 2. 随机数引擎 3. 随机数引擎适配器 4. C中预定义的随机数引擎&#xff0c;引擎适配器 5. 随机数分布 一&#xff1a;C语言中的随机数 <stdlib.h>//初始化随机种子 srand(static_ca…...

容器之docker compose

Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 YAML 文件&#xff0c;您可以配置应用程序需要的所有服务&#xff0c;并使用单个命令来创建和启动这些服务。以下是对 Docker Compose 的详细介绍&#xff1a; 核心概念 服务&#xff08;Services&am…...

MIT机器人运动控制原理浅析-人形机器人

MIT人形机器人基于开发改进的执行器全新设计&#xff0c;通过可感知执行器运动动力学移动规划器(Actuator-Aware Kino-Dynamic Motion Planner)及着地控制器(Landing Controller)等实现机器人的运动控制。 机器人设计 机器人高0.7米&#xff0c;21KG(四肢重量 25%)&#xff0c;…...

开源 WAF 解析:选择最适合你的防护利器

前言 随着网络安全风险的增加&#xff0c;Web 应用防火墙&#xff08;WAF&#xff09;成为保护网站和应用程序免受攻击的关键工具。在众多的选择中&#xff0c;开源 WAF 以其灵活性、可定制性和成本效益备受青睐。本文将深入探讨几种主流开源 WAF 解决方案&#xff0c;帮助你选…...

AirPods Pro新功能前瞻:iOS 18的五大创新亮点

随着科技的不断进步&#xff0c;苹果公司一直在探索如何通过创新提升用户体验。iOS 18的推出&#xff0c;不仅仅是iPhone的一次系统更新&#xff0c;更是苹果生态链中重要一环——AirPods Pro的一次重大升级。 据悉&#xff0c;iOS 18将为AirPods Pro带来五项新功能&#xff0…...

JavaScript中的可选链操作符

在JavaScript中&#xff0c;?. 被称为可选链操作符&#xff08;Optional Chaining Operator&#xff09;。它允许你访问对象的深层属性而不必显式地检查每一层属性是否存在。如果链中的某个属性不存在&#xff0c;表达式将短路返回undefined&#xff0c;而不是抛出一个TypeErr…...

huggingface笔记:gpt2

0 使用的tips GPT-2是一个具有绝对位置嵌入的模型&#xff0c;因此通常建议在输入的右侧而不是左侧填充GPT-2是通过因果语言建模&#xff08;CLM&#xff09;目标进行训练的&#xff0c;因此在预测序列中的下一个标记方面非常强大 利用这一特性&#xff0c;GPT-2可以生成语法连…...

一次业务的批量数据任务的处理优化

文章目录 一次业务的批量数据任务的处理优化业务背景1.0版本 分批处理模式2.0版本 平衡任务队列模式3.0版本 优化调度平衡任务队列模式总结 一次业务的批量数据任务的处理优化 业务背景 一个重新生成所有客户的财务业务指标数据的批量数据处理任务。 1.0版本 分批处理模式 …...

新能源汽车充电站远程监控系统S275钡铼技术无线RTU

新能源汽车充电站的远程监控系统在现代城市基础设施中扮演着至关重要的角色&#xff0c;而钡铼技术的S275无线RTU作为一款先进的物联网数据监测采集控制短信报警终端&#xff0c;为充电站的安全运行和高效管理提供了强大的技术支持。 技术特点和功能 钡铼S275采用了基于UCOSI…...

海外视频媒体发布/发稿:如何在国外媒体以视频的形式宣发

1. 背景介绍 在如今数字化时代&#xff0c;每个国家都拥有着各自的视频媒体平台&#xff0c;而主流媒体也都纷纷加入了视频发布的行列。视频媒体的宣发形式主要包括油管Youtube等视频分享平台&#xff0c;以及图文配合的发布方式。通过在视频中夹带链接&#xff0c;媒体可以以…...

HTML 【实用教程】(2024最新版)

核心思想 —— 语义化 【面试题】如何理解 HTML 语义化 ?仅通过标签便能判断内容的类型&#xff0c;特别是区分标题、段落、图片和表格 增加代码可读性&#xff0c;让人更容易读懂对SEO更加友好&#xff0c;让搜索引擎更容易读懂 html 文件的基本结构 html 文件的文件后缀为 …...

How to Describe Figures in a Research Article

How to Describe Figures in a Research Article DateAuthorVersionNote2024.07.10Dog TaoV1.0Finish the document. 文章目录 How to Describe Figures in a Research ArticleGeneral GuidelinesDetailed DescriptionsCommon Describing Phrases Effective communication of …...

昇思MindSpore学习入门-CELL与参数一

Cell作为神经网络构造的基础单元&#xff0c;与神经网络层(Layer)的概念相对应&#xff0c;对Tensor计算操作的抽象封装&#xff0c;能够更准确清晰地对神经网络结构进行表示。除了基础的Tensor计算流程定义外&#xff0c;神经网络层还包含了参数管理、状态管理等功能。而参数(…...

【k8s中安装rabbitmq】k8s中安装rabbitmq并搭建镜像集群-hostpath版

文章目录 简介一.条件及环境说明二.需求说明三.实现原理及说明四.详细步骤4.1.规划节点标签4.2.创建configmap配置4.3.创建三个statefulset和service headless配置4.4.创建service配置 五.安装完后的配置六.安装说明 简介 k8s集群中搭建rabbitmq集群服务一般都会用到pvc&#x…...

(5) 深入探索Python-Pandas库的核心数据结构:Series详解

目录 前言1. Series 简介2. Series的特点3. Series的创建3.1 使用列表创建Series3.2 使用字典创建Series3.3 使用列表和自定义索引创建Series3.4 指定数据类型和名称 4. Series的索引/切片4.1 下标索引&#xff1a;基于整数位置的索引4.2 基于标签的索引4.3 切片4.4 使用.loc[]…...

JAVA之开发神器——IntelliJ IDEA的下载与安装

一、IDEA是什么&#xff1f; IEAD是JetBrains公司开发的专用于java开发的一款集成开发环境。由于其功能强大且符合人体工程学&#xff08;就是更懂你&#xff09;的优点&#xff0c;深受java开发人员的喜爱。目前在java开发工具中占比3/4。如果你要走java开发方向&#xff0c;那…...

通过Umijs从0到1搭建一个React项目

有一阵时间没写react了&#xff0c;今天通过umi搭建一个demo项目复习一下react&#xff1b;umi是一个可扩展的企业级前端应用框架&#xff0c;在react市场中还是比较火的一个框架。 Umi官方文档&#xff1a;Umi 介绍 (umijs.org) 一、构建项目。 1、安装包管理工具。 官方推…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

LangChain【6】之输出解析器:结构化LLM响应的关键工具

文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器&#xff1f;1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...

统计学(第8版)——统计抽样学习笔记(考试用)

一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征&#xff08;均值、比率、总量&#xff09;控制抽样误差与非抽样误差 解决的核心问题 在成本约束下&#xff0c;用少量样本准确推断总体特征量化估计结果的可靠性&#xff08;置…...

2025-06-01-Hive 技术及应用介绍

Hive 技术及应用介绍 参考资料 Hive 技术原理Hive 架构及应用介绍Hive - 小海哥哥 de - 博客园https://cwiki.apache.org/confluence/display/Hive/Home(官方文档) Apache Hive 是基于 Hadoop 构建的数据仓库工具&#xff0c;它为海量结构化数据提供类 SQL 的查询能力&#xf…...