【C++ / STL】封装红黑树实现map和set
文章目录
- 一. 源码及框架分析
- 1.决定搜索类型的传参
- 思考:为什么要传第一个参数
- 2.KeyOfValue的作用
- 二. 模拟实现map和set
- 1. 实现出复用红黑树框架,并支持insert
- 2. 支持iterator的实现
- iterator实现思路分析
- 【iterator++操作实现详解】
- 3.支持map的[ ]操作
- 4.map和set代码实现
一. 源码及框架分析
1.决定搜索类型的传参
1.这是rb_tree主要成员变量,可以看出,rb_tree是实现单个Key还是pair型,节点的类型并不是写死的,而是由第二个参数Value决定,这样即可以实现Key搜索场景的set,又可以实现Key/Value场景的map
2. 这是map的主要成员变量,从这里可以看出map在复用rb_tree时,第二个参数传的是pair型
3. 这是set的主要成员变量,从这里可以看出set在复用rb_tree时,第一个和第二个参数传的是Key型
思考:为什么要传第一个参数
思考:既然第二个参数决定节点的存储类型,为什么还要再传第一个参数Key呢?
第一个参数Key是给find/erase等函数做形参类型的,对于set,两个参数一样,但对于map,insert的是pair型,find/erase的是Key型。
2.KeyOfValue的作用
在rb_tree内,并不知道Value是一个Key值还是pair,在进行插入比较时,需要比较的是Key,而KeyOfValue可以提取出来相比较的两个数据的Key值,可以在map和set调用rb_tree时传入KeyOfValue的方法
源码是通过std::select1st和std:: identity来实现的,这里我改成了在map和set层实现KOV_M和KOV_S的仿函数传给rb_tree,同样也能实现提取Key的效果,具体看下面的代码实现
二. 模拟实现map和set
1. 实现出复用红黑树框架,并支持insert
参照源码,红黑树的第二个参数决定存储的数据类型,这里就需要对原来实现的红黑树做一下调整
【1】在实现insert时,对比节点大小要用map和set层提供的KeyOfValue来提取出要比较的值
【2】为了支持map的实现,返回值改为pair型,pair的一个参数为插入节点的迭代器,第二个节点为是否成功插入
rb_tree基本结构
//rb_tree
template <class K, class V,class KeyOfValue,class Compare=std::less<K>>
class RBTree
{
public:typedef RBTreeNode<V> Node;typedef RBTreeIterator<V, V&, V*> Iterator;typedef RBTreeIterator<V, const V&, const V*> ConstIterator;std::pair<Iterator,bool> Insert(const V& value);Node* _root=nullptr;Iterator Find(K& key);
private:Node* _root=nullptr;void RorateRL(Node* root);void RorateLR(Node* root);void RorateR(Node* root);void RorateL(Node* root);};
insert实现
template <class K, class V, class KeyOfValue, class Compare>
std::pair<RBTreeIterator<V, V&, V*>, bool> RBTree < K,V, KeyOfValue,Compare>::Insert(const V& value)
{if (_root == nullptr){_root = new Node(value);_root->_color = RBTreeBlack;return { {_root,_root},true };}Node* parent = nullptr; Node* cur = _root;//二叉树规则插入KeyOfValue kov;Compare com;while (cur){ // if (cur->_kv.first < kv.first) if(kov(value)==kov(cur->_value))return { {cur,_root},true };if( com( kov(cur->_value),kov(value) ) ){parent = cur; cur = cur->_right; } //else if (cur->_kv.first > kv.first) else if ( com( kov(value), kov(cur->_value) ) ){parent = cur; cur = cur->_left;}}cur = new Node(value);//判断新增节点使父节点左还是右//if (parent->_value.first < value.first)if(com(kov(parent->_value),kov(value)))parent->_right = cur;elseparent->_left = cur;cur->_parent = parent;while (parent && parent->_color == RBTreeRed){Node* grandfather = parent->_parent;// g//p u//p为g的左代码实现if (parent == grandfather->_left){Node* uncle = grandfather->_right;// u存在且为红,p和u变黑,g变红,改变cur和p的指向,继续向上变;if (uncle && uncle->_color == RBTreeRed){parent->_color = uncle->_color = RBTreeBlack;grandfather->_color = RBTreeRed;cur = grandfather;parent = grandfather->_parent;}// u不存在或存在且为黑else{// g// p u// c//单旋加变色,c为p的左, p变成新的根,p变黑,g变红if (cur == parent->_left){RorateR(grandfather);parent->_color = RBTreeBlack;grandfather->_color = RBTreeRed;}// g// p u// c//双旋加变色,c为p的右,else{RorateLR(grandfather);cur->_color = RBTreeBlack;grandfather->_color = RBTreeRed;}}return { {cur,_root},true };}else{ //这里是p为g的情}return { {cur,_root},true };}return { {cur,_root},true };
}}
封装map
my_map
template<class K, class V>
class KOV_M
{
public:K operator()(const std::pair<K, V> data){return data.first;}
};template<class K, class V, class Compare = std::less<K>>
class map
{
public:typedef typename RBTree<K, std::pair<K, V>, KOV_M<K, V>>::Iterator iterator;typedef typename RBTree< K, std::pair<K, V>, KOV_M<K, V>>::ConstIterator const_iterator;std::pair<iterator, bool> insert(const std::pair<K, V>& p)
{return _tree.Insert(p);
}
private:RBTree<K, std::pair<K, V>, KOV_M<K,V>> _tree;
};
封装set
template<class V>
class KOV_S
{
public:V operator()(const V& data){return data;}
};
template< class V, class Compare =std:: less<V>>
class set
{
public:std::pair<iterator, bool> insert(int value){return _tree.Insert(value);}
private:RBTree<V,V, KOV_S<V>> _tree;
};
2. 支持iterator的实现
参照源码,需要实现iterator的++和–等操作,
iterator实现思路分析
- 整体思路和list的iterator类似,用类封装节点的指针,然后通过重载运算符,使迭代器实现像指针一样的行为
- map和set的迭代器走的是中序遍历,这样才能有序,所以在++和–操作时就要遵循中序遍历的规则
- 支持->等运算符是为了封装map时支持 [ ] 操作
【iterator++操作实现详解】
- 如果cur的右子树不为空,根据二叉树的规则,它的右子树的最左节点就是他的下一个节点,
2. 如果cur的右子树为空,就代表以cur为根的树已经走完了,接下来就要分成两种情况来讨论
【1】cur为父节点的左节点,++操作就是走到cur的父节点
【2】cur为父节点的右节点,这种情况就是以cur的父节点为根的树走完了,需要一直向上更新,直到遇到一个节点是父节点左节点或者走到终点
这里关于end()的实现,源码中是设置了一个哨兵位头节点,它和根互为父节点,左指向最左,右指向最右,这里我用空节点实现的end(),可以实现和源码同样的功能,但在–end()时需要特殊处理一下,让迭代器指向最右节点,具体看–的代码实现
template<class V, class Ref, class Ptr>
class RBTreeIterator
{
public:typedef RBTreeNode<V> Node;//typedef RBTreeIterator<V, V&, V*> Iterator;//typedef RBTreeIterator<V, const V&, const V*> ConstIterator;typedef RBTreeIterator<V, Ref, Ptr> Self;RBTreeIterator(){}RBTreeIterator(Node* node,Node* root) :_node(node), _root(root){}void increment(){if (_node->_right != nullptr){_node = _node->_right;while (_node->_left != nullptr)_node = _node->_left;}else{Node* p = _node->_parent;if (_node == p->_left)_node = p;else{while (p != nullptr && _node == p->_right){_node = p;p = p->_parent;}if (p == nullptr)_node = nullptr;}}}void decrement(){if (_node->_left != nullptr){_node = _node->_left;while (_node->_right != nullptr)_node = _node->_right;}else{Node* p = _node->_parent;while (p != nullptr && _node == p->_left){_node = p;p = p->_parent;}_node = p;}}Node* rightMost(){Node* RightMost = _root;while (RightMost != nullptr && RightMost->_right != nullptr)RightMost = RightMost->_right;return RightMost;}Self& operator++(){increment();return *this;}Self operator++(int){Self tmp = *this;increment();return tmp;}Self& operator--(){if (_node == nullptr)_node = rightMost();elsedecrement();return *this;}Self operator--(int){Self tmp = *this;if (_node == nullptr)_node = rightMost();elsedecrement();return tmp;}bool operator==(Self& y){return _node == y._node;}bool operator!=(Self& y){return _node != y._node;}Ref operator*(){return _node->_value;}Ptr operator->(){return &_node->_value;}
public:Node* _node;Node* _root;
};
3.支持map的[ ]操作
有了insert的实现,实现[]就很简单了,可以复用insert代码,而在这里先前iterator支持的->操作也派上用场了,用来返回pair的第二个参数,具体看代码
4.map和set代码实现
//map
namespace kzz
{template<class K, class V>class KOV_M{public:K operator()(const std::pair<K, V> data){return data.first;}};template<class K, class V, class Compare = std::less<K>>class map{public:typedef typename RBTree<K, std::pair<K, V>, KOV_M<K, V>>::Iterator iterator;typedef typename RBTree< K, std::pair<K, V>, KOV_M<K, V>>::ConstIterator const_iterator;std::pair<iterator, bool> insert(const std::pair<K, V>& p){return _tree.Insert(p);}iterator begin(){return _tree.Begin();}iterator end(){return _tree.End();}const_iterator begin()const{return _tree.Begin();}const_iterator end()const{return _tree.End();}iterator find(K& key){_tree.Find(key);}V& operator[](const K& key){std::pair<iterator,bool> ret= _tree.Insert( std::pair<K,V>(key,V()) );return ret.first->second;}private:RBTree<K, std::pair< K, V>, KOV_M<K,V>> _tree;};
}
//set
namespace kzz
{template<class V>class KOV_S{public:V operator()(const V& data){return data;}};template< class V, class Compare =std:: less<V>>class set{public:typedef typename RBTree<V, const V, KOV_S<V>>::Iterator iterator;typedef typename RBTree<V, const V, KOV_S<V>>::ConstIterator const_iterator;std::pair<iterator, bool> insert(int value){return _tree.Insert(value);}iterator begin(){return _tree.Begin();}iterator end(){return _tree.End();}const_iterator begin()const{return _tree.Begin();}const_iterator end()const{return _tree.End();}iterator find(K& key){_tree.Find(key);}private:RBTree<V,const V, KOV_S<V>> _tree;};
}
//rb_tree
template <class K, class V,class KeyOfValue,class Compare=std::less<K>>
class RBTree
{
public:typedef RBTreeNode<V> Node;typedef RBTreeIterator<V, V&, V*> Iterator;typedef RBTreeIterator<V, const V&, const V*> ConstIterator;std::pair<Iterator,bool> Insert(const V& value);Iterator End(){return Iterator(nullptr, _root);}Iterator Begin(){Node* leftMost = _root; while (leftMost && leftMost->_left) {leftMost = leftMost->_left; }return Iterator(leftMost, _root);}ConstIterator End()const{return ConstIterator(nullptr, _root);}ConstIterator Begin()const{Node* leftMost = _root;while (leftMost && leftMost->_left){leftMost = leftMost->_left;}return ConstIterator(leftMost, _root);}public:Iterator Find(K& key);Node* _root=nullptr;void RorateRL(Node* root);void RorateLR(Node* root);void RorateR(Node* root);void RorateL(Node* root);bool IsBanlance(Node* root);bool check(Node* root,int count,const int blackNum);
};
相关文章:
【C++ / STL】封装红黑树实现map和set
文章目录 一. 源码及框架分析1.决定搜索类型的传参思考:为什么要传第一个参数 2.KeyOfValue的作用 二. 模拟实现map和set1. 实现出复用红黑树框架,并支持insert2. 支持iterator的实现iterator实现思路分析【iterator操作实现详解】 3.支持map的[ ]操作4.map和set代码…...
记录: Windows下远程Liunx 系统xrdp 用到的一些小问题(免费踩坑 记录)
采用liunx Ubuntu22.04版本以下,需要安装 xrdp 或者VNC 具体过程就是下载 在linux命令行里 首先更新软件包:sudo apt update 安装xrdp服务:sudo apt install xrdp 启动XRDP:sudo systemctl start xrdp(如果在启动的…...
WordPress 文章和页面:它们的区别是什么?
很多刚接触WordPress的用户,在创建网站内容时往往会遇到这样一个问题:“我应该用‘文章’还是‘页面’?”虽然两者都能发布内容,但它们之间到底有什么区别呢?这篇文章将从易于理解的角度,帮助大家厘清WordP…...
【工具变量】各省市场化指数-杨兴权版共三个方法(1997-2023年)
市场化指数是衡量中国各地区市场化改革进程的重要指标。本次数据基于杨兴全、马连福和夏立军三位学者的研究成果,系统整理并更新了我国1997-2023年间31个省、自治区、直辖市的市场化指数,便于研究者进行横向和纵向比较分析。 一、数据介绍 数据名称&…...
Android App View——团结引擎车机版实现安卓应用原生嵌入 3D 开发场景
团结引擎 1.5.0 版本已于 4 月 14 日正式发布,从 1.5.0 版本开始,团结引擎车机版带来了一个激动人心的新能力 —— Android App View。现在,开发者可以将任意第三方安卓应用以 2D 组件或 3D 组件的形式,原生嵌入到 Tuanjie 开发的…...
完整的 CentOS 6.10 虚拟机安装启动脚本
好的!下面是一个 完整的 CentOS 6.10 虚拟机安装启动脚本,专为你在 macOS(M 系芯片) QEMU(x86_64 软件模拟) 环境设计,确保你能顺利启动并安装一个接近 Red Hat 6.4 的开发环境。 ⸻ ✅ 前提准…...
如何远程执行脚本不留痕迹
通常我们在做远程维护的时候,会有这么一个需求,就是我想在远程主机执行一个脚本,但是这个脚本我又不想保留在远程主机上,那么有人就说了,那就复制过去再登录远程执行不就行了吗?嗯嗯,但是这还不…...
观测云:从云时代走向AI时代
过去十年,云计算让企业的数据处理能力实现了指数级增长,而观测云作为全栈监控观测平台,见证并参与了这一进程。通过强大的数据采集、处理与展示能力,观测云帮助数百家企业实现了对 IT 基础设施、应用服务、业务链路的全面掌控。 …...
解密企业级大模型智能体Agentic AI 关键技术:MCP、A2A、Reasoning LLMs- consistency is the key
解密企业级大模型智能体Agentic AI 关键技术:MCP、A2A、Reasoning LLMs- consistency is the key DeepSeek v3的时候,它模型已经足够强大到能带来consistency稳定性。所以当这个DeepSeek R1 Zero或者DeepSeek R1使用GRPO进行训练的时候,它能够…...
鸿蒙OSUniApp 实现图片上传与压缩功能#三方框架 #Uniapp
UniApp 实现图片上传与压缩功能 前言 在移动应用开发中,图片上传是一个非常常见的需求。无论是用户头像、朋友圈图片还是商品图片,都需要上传到服务器。但移动设备拍摄的图片往往尺寸较大,直接上传会导致流量消耗过大、上传时间过长&#x…...
SymPy | 如何提取指定项的系数
SymPy 是 Python 中一个强大的符号计算库,广泛应用于数学、物理和工程领域的符号运算。在代数表达式的处理中,提取特定项的系数是一项常见且重要的操作。本文将详细介绍 SymPy 中提取指定项系数的多种方法,并通过丰富的示例帮助读者掌握这些技…...
MUSE Pi Pro 更换kernel内核及module模块
视频讲解: MUSE Pi Pro 更换kernel内核及module模块 脚本仓库: https://github.com/LitchiCheng/MUSE-Pi-Pro-Learning 结合上期编译内核,编译成功后的输出如下: 输入 uname -a 可以看到如下信息,未修改的内核时间在 …...
java每日精进 5.14【参数校验】
参数校验 1.1概述 本文使用 Hibernate Validator 框架对 RESTful API 接口的参数进行校验,确保数据入库的正确性。 例如,在用户注册时,校验手机号格式、密码强度等。如果校验失败,抛出 ConstraintViolationException 或相关异…...
CPS联盟+小程序聚合平台分销返利系统开发|小红书番茄网盘CPA拉新推广全解析
导语: 在私域流量与社交电商爆发的时代,CPS联盟分销返利系统与小红书CPA拉新推广成为企业增长的核心引擎。本文深度解析如何通过小程序聚合平台开发、多层级返利机制搭建及精准CPA推广策略,快速占领市场,实现用户裂变与收益倍增。…...
基于EFISH-SCB-RK3576/SAIL-RK3576的光伏逆变器控制器技术方案
(国产化替代J1900的能源物联网解决方案) 一、硬件架构设计 电力转换与控制模块 高精度功率控制: Cortex-M0硬实时核驱动多相PWM(频率>200kHz),动态调节DC-AC转换误差<0.5%FPGA实现MPPT算法…...
HarmonyOS NEXT 适配高德地图FlutterSDK实现地图展示,添加覆盖物和移动Camera
HarmonyOS NEXT 适配高德地图 Flutter SDK 实现地图展示,添加覆盖物和移动 Camera 在现代移动应用开发中,地图功能是许多应用的核心组成部分之一。HarmonyOS NEXT 提供了强大的跨平台开发能力,而高德地图 Flutter SDK 则为开发者提供了丰富的…...
计算机网络:手机和基站之间是通过什么传递信息的?怎么保证的防衰减,抗干扰和私密安全的?
手机与基站之间的通信依赖无线电磁波信号,其传输介质、频率选择、抗衰减/抗干扰技术及隐私保护机制共同构成了现代移动通信的核心。以下从技术原理到实际应用逐一解析: 一、信号本质与传输介质 1. 信号类型 电磁波:手机与基站通过射频(RF)电磁波传递信息,采用数字调制技…...
C#调用C++dll 过程记录
C#调用Cdll 过程记录 问题:1、设置修改记录2 修改对应问题3 继续出问题4 许久之后的转机5 最后的成功 如题,过程记录 问题: 提示:main 已经在 dllmain.obj 中定义,针对该问题作进一步的处理 1、设置修改记录 &…...
Vue百日学习计划Day4-8——Gemini版
番茄时钟: 每个番茄钟为25分钟学习,之后休息5分钟。每完成4个番茄钟,进行一次15-30分钟的长休息。灵活性: 这仍然是一个建议性计划。某些主题(尤其是 Flexbox 和 Grid)可能需要比预期更多的时间来练习和理解…...
DHCP协议
DHCP协议 1、掌握DHCP的工作原理 2、会在Windows server上去部署DHCP服务 3、抓流量 正常收到攻击后 一、DHCP 1、DHCP基本概念 dhcp(动态主机配置协议):主要就是给客户机提供TCP/IP参数(IP地址、子网掩码、网关、DNS等) 2、好处 减少管理员工作…...
级联与端到端对话系统架构解析:以Moshi为例
一、对话系统架构对比 1.1 级联对话系统(Cascaded Dialogue Systems) 传统级联系统采用多阶段处理流程: 语音识别(ASR):将24kHz音频信号通过卷积神经网络(CNN)和Transformer转换为…...
3、ubantu系统docker常用命令
1、自助查看docker命令 1.1、查看所有命令 docker 客户端非常简单,可以直接输入 docker 命令来查看到 Docker 客户端的所有命令选项。 angqiangwangqiang:~$ dockerUsage: docker [OPTIONS] COMMANDA self-sufficient runtime for containersCommon Commands:ru…...
【leetcode】349. 两个数组的交集
文章目录 代码1.set()2. 哈希表3. 数组 给定两个数组 nums1 和 nums2 ,返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1: 输入:nums1 [1,2,2,1], nums2 [2,2] 输…...
BGP联邦和发射试验
一、要求 二、需求分析 1. **拓扑与地址规划** - **AS1**:环回16.1.1.0/24需宣告,192.168.1.0/24不宣告。 - **AS3**:环回11.1.1.0/24需宣告,192.168.2.0/24不宣告。 - **AS2**:使用172.16.0.0/16划分子…...
LeetCode Hot100 (1/100)
目录 一、有关数组和动态数组的排序(sort函数) 1.普通数组的排序 基本用法 降序排序 2.vector的排序 基本用法 降序排序 二、数组长度和一些vector的基本语法 1. 静态数组长度计算 2. 安全获取数组长度(C17 起) 3.vecto…...
LeetCode热题100--234.回文链表--简单
1. 题目 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true 示例 2: 输入…...
Java—接口和抽象类
一、接口 Java 接口(Interface) 是面向对象编程中用于定义行为规范的核心机制。接口通过抽象方法约定“能做什么”,而不关心“如何做”,从而实现多态和代码解耦。 1.1 接口的特点 接口用interface定义接口中全为抽象方法默认用p…...
CycleISP: Real Image Restoration via Improved Data Synthesis通过改进数据合成实现真实图像恢复
摘要 大规模数据集的可用性极大释放了深度卷积神经网络(CNN)的潜力。然而,针对单图像去噪问题,获取真实数据集成本高昂且流程繁琐。因此,图像去噪算法主要基于合成数据开发与评估,这些数据通常通过广泛假设…...
算法题(146):最大子段和
、 审题: 本题需要我们找到给定数组中子段之和和最大的sum值 思路: 方法一:暴力解法 我们可以使用双层for循环,第一层循环负责遍历每一个数组元素,然后分别以他们为子段起点,第二层循环从第一层循环的索引开…...
centos6.10在Macbook m芯片上使用
非常好!用 CentOS 6.10 替代 6.4 是一个明智的选择 ✅,原因如下: ⸻ ✅ 为什么选 CentOS 6.10 更好 对比项 CentOS 6.4 CentOS 6.10 发布年份 2013 年 2018 年(CentOS 6 系列最终版) 内核版本 2.6.32-358 2.6.32-75…...
OA 系统办公自动化包含哪些内容,关键功能模块与操作要点说明
在企业数字化转型浪潮中,OA 系统常被片面认知为请假审批、文件收发的工具,未能发挥其核心价值。部分企业引入 OA 后,出现员工抵触、流程卡顿、系统闲置等问题,根源在于对其功能定位模糊、应用模式僵化,导致无法实现预期…...
AI智能体的现状和应用前景
AI智能体的现状 AI智能体(AI Agents)是指能够感知环境、做出决策并执行任务的智能系统。它们通常结合了机器学习、自然语言处理、计算机视觉等技术,能够在复杂环境中自主运行。目前,AI智能体已经在多个领域取得了显著进展。 在工业领域,AI智能体被用于自动化生产线、质量…...
操作系统实验 实验3 存储器分配与回收
1.实验目的 了解动态分区分配方式中使用的数据结构和分配算法,并进一步加深动态分区存储管理方式及其实现过程的理解。 2.实验要求 用C语言实现首次适应算法的动态分区分配过程alloc()和回收过程free()。 一、实验内容: 1.实验内容 用C语言实…...
408考研逐题详解:2009年第13题
2009年第13题 浮点数加、减运算过程一般包括对阶、尾数运算、规格化、舍入和判溢出等步骤。设浮点数的阶码和尾数均采用补码表示,且位数分别为 5 位和 7 位(均含 2 位符号位)。若有两个数 X 2 7 29 / 32 X2^7\times29/32 X2729/32, Y 2 …...
什么是虚拟同步发电机
虚拟同步发电机(Virtual Synchronous Generator, VSG) 是一种基于电力电子技术的先进控制策略,通过模拟传统同步发电机的机电特性和动态行为,使逆变器或储能系统能够像传统发电机一样为电网提供惯性支撑、频率调节和电压稳定性支持…...
性能比拼: Linkerd vs. Istio
本内容是对知名性能评测博主 Anton Putra Linkerd vs. Istio (Rust vs. C) performance benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 在本内容中,我们将对比 Kubernetes 服务网格中的 Istio 和 Linkerd。 相关代码详见 github 我们将运行…...
FPGA: Xilinx Kintex 7实现PCIe接口
在Xilinx Kintex-7系列FPGA上实现PCIe(Peripheral Component Interconnect Express)接口,通常使用Xilinx提供的7 Series Integrated Block for PCIe IP核,结合Vivado设计流程。以下是实现PCIe接口的详细步骤和关键点,适…...
《Effective Python》第2章 字符串和切片操作——Python 字符串格式化的现代选择f-strings
引言 本篇博客基于学习《Effective Python》第三版 Chapter 2: Strings and Slicing 的 Item 11 “Prefer Interpolated F-Strings Over C-style Format Strings and str.format” 的总结与延伸。 字符串格式化是 Python 编程中的常见操作,用于动态生成可读性高的…...
vue 去掉右边table的下拉条与下面的白色边框并补充满
::v-deep table {width: 100% !important; } ::v-deep .el-table::after, .el-table::before {display: none !important; }/* 隐藏滚动条但保留滚动功能 */ ::v-deep .el-table__body-wrapper::-webkit-scrollbar {width: 0 !important;height: 0 !important; }::v-deep .el-t…...
RabbitMq消息阻塞,立即解决方案
如果目前你的 RabbitMQ 消费者 被卡住不再消费消息,且消息已经到达消费者绑定队列,但Spring Cloud Stream 没有继续触发 StreamListener 的方法执行。这类问题一般是因为消费者线程阻塞或消息被 RabbitMQ 拒绝投递。我们可以按照下面的步骤紧急处理&…...
单片机-STM32部分:14、SPI
飞书文档https://x509p6c8to.feishu.cn/wiki/VYYnwOc9Zi6ibFk36lYcPQdRnlf 什么是SPI SPI 是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola(摩托罗拉)首先在其MC68HCXX系列处理器上定义的。 SPI,是一种高速的&…...
Selenium-Java版(操作元素)
选择和操控元素的基本方法 前言 选择元素 选择元素的方法 根据 id属性选择元素 根据class属性选择元素 根据tag名选择元素 通过WebElement对象选择元素 示例 等待界面元素出现 原因 解决 操控元素 点击元素 输入框 获取元素信息 获取元素文本内容 获取…...
20052012世界银行中国企业调查数据-社科数据
2005&2012世界银行中国企业调查数据-社科数据https://download.csdn.net/download/paofuluolijiang/90623828https://download.csdn.net/download/paofuluolijiang/90623828 世界银行中国企业调查数据(World Bank Enterprise Surveys Data)是国际金…...
学习黑客NFC技术详解
NFC技术详解:近距离通信的无线桥梁 📱💳 学习目标:了解NFC技术的基本原理、应用场景及安全注意事项,掌握这一日益普及的近场通信技术 1. NFC的概念与基础 📡 NFC(Near Field Communication&…...
Java问题排查常用命令行工具速查表
Java问题排查常用命令行工具速查表 工具典型用途常用命令示例说明/场景jps列出本机所有Java进程jps -l获取Java进程PID和主类名,配合其它工具使用jcmd动态诊断、堆heap dump、线程dump等jcmd helpjcmd VM.flagsjcmd GC.heap_infojcmd Thread.print功能最全…...
近期搬了个家,停更了几天,明天继续哈~
近期搬了个家,停更了几天,明天继续哈~ 近期搬家比较离谱,第一天下暴雨,冰雹,停电,第二天又停电两小时,截止14号晚上11:30终于完工 了,从西二的20 号楼到西三的19号楼&am…...
C#高级编程:IO和序列化
在 C# 编程中,输入输出(IO)和序列化是两个至关重要的概念,它们为数据的存储、读取以及在不同环境间的传输提供了强大的支持。无论是开发小型应用程序,还是构建复杂的企业级系统,深入理解并熟练运用 IO 和序列化技术都是必不可少的。 一、C# 中的 IO 基础 1、文件流…...
PyQt5完整指南:从入门到实践
引言 PyQt5是Python编程语言的一个GUI(图形用户界面)工具包,它是Qt5应用程序框架的Python绑定。Qt是一个跨平台的C应用程序开发框架,被广泛用于开发GUI程序和非GUI程序。PyQt5让Python开发者能够使用Python语言享受到Qt框架的强大…...
C#高级编程:加密解密
在数字化时代,数据安全是每个应用程序都必须重视的环节。无论是用户的个人信息、敏感的商业数据,还是重要的系统配置,都需要得到妥善的保护。C# 作为一种广泛应用的编程语言,提供了丰富且强大的加密解密功能,帮助开发者构建安全可靠的应用。本文将深入探讨 C# 高级编程中的…...
银行卡真伪验证助力金融合规-银行卡实名认证接口
在数字化时代,金融交易日益频繁,用户身份与银行卡信息的真实性核验成为保障资金安全、防止欺诈行为的关键环节。无论是在线支付、网络借贷、电商平台,还是社交软件、金融服务APP,均需对用户的银行卡进行严格的实名认证。为满足企业…...