红黑树解析
目录
一、引言
二、红黑树的概念与性质
2.1 红黑树的概念
2.2 红黑树的性质
三、红黑树的节点定义与结构
3.1 节点定义
四、红黑树的插入操作
4.1 插入步骤
4.2 插入代码实现
五、红黑树的验证
5.1 验证步骤
5.2 验证代码实现
六、红黑树迭代器的实现
6.1 迭代器的定义
6.2 迭代器的递增和递减操作
七、红黑树模拟实现 map 与 set
7.1 set 的模拟实现
7.2 map 的模拟实现
八、总结
一、引言
在数据结构的世界里,平衡二叉搜索树是高效组织和查询数据的重要工具。红黑树作为平衡二叉搜索树的一种,因其良好的平衡特性和相对简单的实现,在许多场景中得到广泛应用,尤其是在C++ 的标准模板库(STL)中, map 和 set 等关联式容器的底层实现就依赖于红黑树。本文将深入探讨红黑树的原理、实现细节,并结合代码详细展示其在模拟 map 和 set 容器中的应用。
二、红黑树的概念与性质
2.1 红黑树的概念
红黑树是一种二叉搜索树,在每个节点上增加了一个存储位来表示节点的颜色,颜色可以是红色(Red)或黑色(Black)。通过对从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,从而达到近似平衡的状态。
2.2 红黑树的性质
1. 节点颜色性质:每个节点不是红色就是黑色。
2. 根节点性质:根节点是黑色的。
3. 红色节点性质:如果一个节点是红色的,则它的两个孩子节点是黑色的。
4. 黑色节点高度性质:对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
5. 叶子节点性质:每个叶子节点(此处的叶子节点指的是空节点)都是黑色的。
这些性质保证了红黑树的最长路径不会超过最短路径的两倍,使得树的高度相对平衡,从而在插入、删除和查找操作上都能保持高效。
三、红黑树的节点定义与结构
3.1 节点定义
在C++ 中,我们可以如下定义红黑树的节点:
cpp// 节点的颜色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; // 节点的颜色};
这里将节点的默认颜色设为红色,主要是为了在插入新节点时,尽量减少对树结构调整的次数。因为插入红色节点比插入黑色节点更不容易破坏红黑树的性质,后续可以通过旋转和变色操作来恢复性质。3.2 红黑树结构
为了方便实现关联式容器,我们在红黑树的实现中增加一个头结点。头结点颜色为黑色,其 _pParent 域指向红黑树的根节点, _pLeft 域指向红黑树中最小的节点, _pRight 域指向红黑树中最大的节点。以下是红黑树类的基本框架:
cpptemplate<class K, class ValueType, class KeyOfValue>class RBTree{typedef RBTreeNode<ValueType> Node;typedef Node* PNode;public:typedef RBTreeIterator<ValueType, ValueType*, ValueType&> Iterator;RBTree();~RBTree();// 迭代器相关Iterator Begin() { return Iterator(_pHead->_pLeft); }Iterator End() { return Iterator(_pHead); }// 插入操作pair<Iterator, bool> Insert(const ValueType& data);// 清空树void Clear();// 查找操作Iterator Find(const K& key);// 容量相关size_t Size() const;bool Empty() const;private:PNode _pHead;size_t _size; // 红黑树中有效节点的个数};
四、红黑树的插入操作
4.1 插入步骤
红黑树的插入操作分为两步:
1. 按照二叉搜索树规则插入新节点:从根节点开始,根据新节点值与当前节点值的大小比较,向左或向右遍历树,直到找到合适的插入位置,插入新节点。新插入节点默认颜色为红色。
2. 检测并修复红黑树性质:由于新插入节点为红色,可能会违反红黑树的性质(主要是性质3:不能有连在一起的红色节点),此时需要对树进行调整,通过旋转和变色操作来恢复红黑树的性质。
4.2 插入代码实现
cpptemplate<class K, class ValueType, class KeyOfValue>pair<typename RBTree<K, ValueType, KeyOfValue>::Iterator, bool> RBTree<K, ValueType, KeyOfValue>::Insert(const ValueType& data){PNode& pRoot = _pHead->_pParent;if (nullptr == pRoot){pRoot = new Node(data, BLACK);pRoot->_pParent = _pHead;_pHead->_pLeft = _pHead->_pRight = pRoot;_size++;return make_pair(Iterator(pRoot), true);}KeyOfValue kofv;PNode pCur = pRoot;PNode pParent = nullptr;while (pCur){if (kofv(pCur->_data) > kofv(data)){pParent = pCur;pCur = pCur->_pLeft;}else if (kofv(pCur->_data) < kofv(data)){pParent = pCur;pCur = pCur->_pRight;}else{return make_pair(Iterator(pCur), false);}}pCur = new Node(data);pCur->_pParent = pParent;if (kofv(pParent->_data) > kofv(data)){pParent->_pLeft = pCur;if (_pHead->_pLeft == _pHead){_pHead->_pLeft = pCur;}}else{pParent->_pRight = pCur;if (_pHead->_pRight == _pHead){_pHead->_pRight = pCur;}}_size++;// 检测并修复红黑树性质while (pParent && pParent->_color == RED){PNode grandFather = pParent->_pParent;if (pParent == grandFather->_pLeft){PNode uncle = grandFather->_pRight;// 情况一:叔叔节点存在且为红if (uncle && uncle->_color == RED){pParent->_color = BLACK;uncle->_color = BLACK;grandFather->_color = RED;pCur = grandFather;pParent = pCur->_pParent;}else{// 情况二:叔叔节点不存在或为黑if (pCur == pParent->_pRight){_RotateLeft(pParent);swap(pParent, pCur);}pParent->_color = BLACK;grandFather->_color = RED;_RotateRight(grandFather);}}else{PNode uncle = grandFather->_pLeft;if (uncle && uncle->_color == RED){pParent->_color = BLACK;uncle->_color = BLACK;grandFather->_color = RED;pCur = grandFather;pParent = pCur->_pParent;}else{if (pCur == pParent->_pLeft){_RotateRight(pParent);swap(pParent, pCur);}pParent->_color = BLACK;grandFather->_color = RED;_RotateLeft(grandFather);}}}_pHead->_pParent->_color = BLACK;return make_pair(Iterator(pCur), true);}
上述代码中, _RotateLeft 和 _RotateRight 分别是左旋和右旋操作的函数,实现如下:
cpptemplate<class K, class ValueType, class KeyOfValue>void RBTree<K, ValueType, KeyOfValue>::_RotateLeft(PNode pParent){PNode pSubR = pParent->_pRight;PNode pSubRL = pSubR->_pLeft;pParent->_pRight = pSubRL;if (pSubRL){pSubRL->_pParent = pParent;}pSubR->_pLeft = pParent;PNode pPParent = pParent->_pParent;pParent->_pParent = pSubR;if (pPParent == nullptr){_pHead->_pParent = pSubR;}else if (pPParent->_pLeft == pParent){pPParent->_pLeft = pSubR;}else{pPParent->_pRight = pSubR;}pSubR->_pParent = pPParent;}template<class K, class ValueType, class KeyOfValue>void RBTree<K, ValueType, KeyOfValue>::_RotateRight(PNode pParent){PNode pSubL = pParent->_pLeft;PNode pSubLR = pSubL->_pRight;pParent->_pLeft = pSubLR;if (pSubLR){pSubLR->_pParent = pParent;}pSubL->_pRight = pParent;PNode pPParent = pParent->_pParent;pParent->_pParent = pSubL;if (pPParent == nullptr){_pHead->_pParent = pSubL;}else if (pPParent->_pLeft == pParent){pPParent->_pLeft = pSubL;}else{pPParent->_pRight = pSubL;}pSubL->_pParent = pPParent;}
五、红黑树的验证
5.1 验证步骤
红黑树的检测分为两步:
1. 检测是否满足二叉搜索树性质:通过中序遍历,检查遍历结果是否为有序序列。
2. 检测是否满足红黑树性质:检查根节点是否为黑色,以及每条路径上黑色节点的个数是否相同等性质。
5.2 验证代码实现
cpptemplate<class K, class ValueType, class KeyOfValue>bool RBTree<K, ValueType, KeyOfValue>::IsValidRBTree(){PNode pRoot = _pHead->_pParent;// 空树也是红黑树if (nullptr == pRoot){return true;}// 检测根节点是否为黑色if (pRoot->_color!= BLACK){std::cout << "违反红黑树性质二:根节点必须为黑色" << std::endl;return false;}// 获取任意一条路径中黑色节点的个数size_t blackCount = 0;PNode pCur = pRoot;while (pCur){if (pCur->_color == BLACK){blackCount++;}pCur = pCur->_pLeft;}// 检测是否满足红黑树的性质,k用来记录路径中黑色节点的个数size_t k = 0;return _IsValidRBTree(pRoot, k, blackCount);}template<class K, class ValueType, class KeyOfValue>bool RBTree<K, ValueType, KeyOfValue>::_IsValidRBTree(PNode pRoot, size_t k, const size_t blackCount){// 走到null之后,判断k和black是否相等if (nullptr == pRoot){if (k!= blackCount){std::cout << "违反性质四:每条路径中黑色节点的个数必须相同" << std::endl;return false;}return true;}// 统计黑色节点的个数if (pRoot->_color == BLACK){k++;}// 检测当前节点与其双亲是否都为红色PNode pParent = pRoot->_pParent;if (pParent && pParent->_color == RED && pRoot->_color == RED){std::cout << "违反性质三:没有连在一起的红色节点" << std::endl;return false;}return _IsValidRBTree(pRoot->_pLeft, k, blackCount) &&_IsValidRBTree(pRoot->_pRight, k, blackCount);}
六、红黑树迭代器的实现
6.1 迭代器的定义
迭代器是红黑树与用户交互的重要接口,它可以方便地遍历红黑树。我们定义迭代器类如下:
cpptemplate<class ValueType, class Pointer, class Reference>class RBTreeIterator{typedef RBTreeNode<ValueType> Node;typedef RBTreeIterator<ValueType, Pointer, Reference> Self;public:RBTreeIterator(Node* node = nullptr) : _pNode(node) {}Reference operator*() { return _pNode->_data; }Pointer operator->() { return &(_pNode->_data); }Self& operator++(){_Increament();return *this;}Self operator++(int){Self tmp(*this);_Increament();return tmp;}Self& operator--(){_Decreament();return *this;}Self operator--(int){Self tmp(*this);_Decreament();return tmp;}bool operator==(const Self& s) const { return _pNode == s._pNode; }bool operator!=(const Self& s) const { return _pNode!= s._pNode; }private:void _Increament(){if (_pNode->_pRight){_pNode = _pNode->_pRight;while (_pNode->_pLeft){_pNode = _pNode->_pLeft;}}else{Node* pParent = _pNode->_pParent;while (pParent && _pNode == pParent->_pRight){_pNode = pParent;pParent = pParent->_pParent;}_pNode = pParent;}}void _Decreament(){if (_pNode->_color == RED && _pNode->_pParent->_pParent == _pNode){_pNode = _pNode->_pRight;}else if (_pNode->_pLeft){_pNode = _pNode->_pLeft;while (_pNode->_pRight){_pNode = _pNode->_pRight;}}else{Node* pParent = _pNode->_pParent;while (pParent && _pNode == pParent->_pLeft){_pNode = pParent;pParent = pParent->_pParent;}_pNode = pParent;}}Node* _pNode;};
6.2 迭代器的递增和递减操作
迭代器的递增操作 operator++ 用于找到当前节点的下一个节点。如果当前节点有右子树,那么下一个节点就是右子树中最左侧的节点;如果当前节点没有右子树,则向上查找,直到找到一个是其双亲节点左孩子的节点,该双亲节点就是下一个节点。
迭代器的递减操作 operator-- 则相反,用于找到当前节点的前一个节点。如果当前节点是头结点且颜色为红色,那么前一个节点是右子树中最大的节点;如果当前节点有左子树,那么前一个节点就是左子树中最右侧的节点;如果当前节点没有左子树,则向上查找,直到找到一个是其双亲节点右孩子的节点,该双亲节点就是前一个节点。
七、红黑树模拟实现 map 与 set
7.1 set 的模拟实现
set 是一种关联式容器,其底层结构为红黑树。`在 set 中,每个元素的值同时也是其键值,元素是唯一且有序的。下面是 set 类的模拟实现代码:
cpp
namespace bit
{template<class K>class set{private:// 定义仿函数用于提取键值struct KeyOfValue{const K& operator()(const K& key) const{return key;}};// 底层使用红黑树存储数据typedef RBTree<K, K, KeyOfValue> RBTreeType;public:typedef typename RBTreeType::Iterator iterator;set() {}// 迭代器相关iterator begin() { return _tree.Begin(); }iterator end() { return _tree.End(); }// 容量相关size_t size() const { return _tree.Size(); }bool empty() const { return _tree.Empty(); }// 插入操作pair<iterator, bool> insert(const K& data){return _tree.Insert(data);}// 清空操作void clear() { _tree.Clear(); }// 查找操作iterator find(const K& key) { return _tree.Find(key); }private:RBTreeType _tree;};
}
在上述代码中,通过定义 KeyOfValue 仿函数,将元素值直接作为键值。然后利用前面实现的红黑树类 RBTree 来存储和管理元素,对外提供 set 容器常用的接口,如插入、查找、遍历等。
7.2 map 的模拟实现
map 也是关联式容器,它存储的是键值对( pair ),其中键值是唯一且有序的,通过键值可以快速查找对应的值。以下是 map 类的模拟实现:
cpp
namespace bit
{template<class K, class V>class map{private:// 定义键值对类型typedef pair<K, V> valueType;// 定义仿函数用于提取键值struct KeyOfValue{const K& operator()(const valueType& v) const{return v.first;}};// 底层使用红黑树存储数据typedef RBTree<K, valueType, KeyOfValue> RBTreeType;public:typedef typename RBTreeType::Iterator iterator;map() {}// 迭代器相关iterator begin() { return _tree.Begin(); }iterator end() { return _tree.End(); }// 容量相关size_t size() const { return _tree.Size(); }bool empty() const { return _tree.Empty(); }// 插入操作pair<iterator, bool> insert(const valueType& data){return _tree.Insert(data);}// 重载 [] 运算符,方便通过键值访问对应的值V& operator[](const K& key){pair<iterator, bool> ret = _tree.Insert(valueType(key, V()));return ret.first->second;}const V& operator[](const K& key) const{iterator it = _tree.Find(key);return it->second;}// 清空操作void clear() { _tree.Clear(); }// 查找操作iterator find(const K& key) { return _tree.Find(key); }private:RBTreeType _tree;};
}
在 map 的实现中,通过 KeyOfValue 仿函数从键值对中提取键值。同样基于红黑树实现数据存储和管理,并且重载了 [] 运算符,使得可以像使用数组一样通过键值方便地访问和修改对应的值。
八、总结
红黑树通过巧妙地利用节点颜色和一些性质,在保证树近似平衡的同时,实现了高效的插入、删除和查找操作。在C++ 中, map 和 set 等关联式容器借助红黑树的特性,为我们提供了快速、有序的数据存储和访问方式。通过深入理解红黑树的原理和实现细节,我们不仅能更好地使用这些容器,还能在遇到类似数据组织和查询需求时,灵活运用红黑树来设计高效的数据结构。
希望本文能帮助大家对红黑树及其在C++ 关联式容器中的应用有更清晰、深入的认识。如果有任何疑问或建议,欢迎交流探讨。
相关文章:
红黑树解析
目录 一、引言 二、红黑树的概念与性质 2.1 红黑树的概念 2.2 红黑树的性质 三、红黑树的节点定义与结构 3.1 节点定义 四、红黑树的插入操作 4.1 插入步骤 4.2 插入代码实现 五、红黑树的验证 5.1 验证步骤 5.2 验证代码实现 六、红黑树迭代器的实现 6.1 迭代器的…...
在线文档管理系统 spring boot➕vue|源码+数据库+部署教程
📌 一、项目简介 本系统采用Spring Boot Vue ElementUI技术栈,支持管理员和员工两类角色,涵盖文档上传、分类管理、公告发布、员工资料维护、部门岗位管理等核心功能。 系统目标是打造一个简洁高效的内部文档管理平台,便于员工…...
Python3 简易DNS服务器实现
使用Python3开发一个简单的DNS服务器,支持配置资源记录(RR),并能通过dig命令进行查询。 让自己理解DNS原理 实现方案 我们将使用socketserver和dnslib库来构建这个DNS服务器。dnslib库能帮助我们处理DNS协议的复杂细节。 1. 安装依赖 首先确保安装了d…...
雾锁王国开服联机教程-专用服务器
一。阿里云服务器搭建 服务器地址:1分钟畅玩!一键部署联机服务器 《雾锁王国(Enshrouded)》融合了生存、制作以及动作 RPG 战斗,游戏背景设定在了一个基于体素构筑的辽阔大陆。无论是攀登山脉还是跨越沙漠࿰…...
鸿蒙OSUniApp 开发的一键分享功能#三方框架 #Uniapp
使用 UniApp 开发的一键分享功能 在移动应用开发中,分享功能几乎是必不可少的一环。一个好的分享体验不仅能带来更多用户,还能提升产品的曝光度。本文将详细讲解如何在 UniApp 框架下实现一个简单高效的一键分享功能,适配多个平台。 各平台分…...
Hive PredicatePushDown 谓词下推规则的计算逻辑
1. PredicatePushDown 谓词下推 谓词下推的处理顺序是先处理子节点的操作,子节点都处理完,然后处理父节点。 select web_site_sk from (select web_site_sk,web_name from web_site where web_cityPleasant Hill ) t where web_name <> site_…...
2024东北四省ccpc
F题 解题思路 数论 有限小数的条件 p q \frac{p}{q} qp 在 k k k 进制下是有限小数,当且仅当 q q q 的所有质因数都是 p p p 或 k k k 的质因数。 即,若 q q q 的质因数分解为 q ∏ i p i a i q \prod_{i} p_i^{a_i} q∏ipiai&#x…...
【C语言】初阶数据结构相关习题(二)
🎆个人主页:夜晚中的人海 今日语录:知识是从刻苦劳动中得来的,任何成就都是刻苦劳动的结果。——宋庆龄 文章目录 🎄一、链表内指定区间翻转🎉二、从链表中删去总和值为零的节点🚀三、链表求和&…...
DeepSeek执行流程加速指南:跨框架转换与编译优化的核心策略全解析
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
解决 Conda 安装 PyTorch 1.1.0 报错:excluded by strict repo priority(附三种解决方案)
# 💥解决 Conda 安装 PyTorch 1.1.0 报错问题:excluded by strict repo priority在使用旧版本 PyTorch(例如 1.1.0)时,有些开发者会遇到以下 conda 安装报错:LibMambaUnsatisfiableError: package pytorch-…...
面试从微前端拓展到iframe是如何通信的
一、跨域通信 1、父页面发消息给 iframe const iframe document.getElementById(myIframe); iframe.contentWindow.postMessage(form parent, https://iframe-domain.com)// iframe 接收 window.addEventListener(message, (event) > {if (event.origin ! https://paren…...
PyTorch循环神经网络(Pytotch)
文章目录 循环神经网络(RNN)简单的循环神经网络长短期记忆网络(LSTM)门控循环单元(GRU) 循环神经网络(RNN) 循环神经网络(RecurrentNeuralNetwork,RNN&#…...
django中用 InforSuite RDS 替代memcache
在 Django 项目中,InforSuite RDS(关系型数据库服务)无法直接替代 Memcached,因为两者的设计目标和功能定位完全不同: 特性MemcachedInforSuite RDS核心用途高性能内存缓存,临时存储键值对数据持久化关系型…...
Git 常用命令详解
Git 常用命令详解(含详细示例) 本文整理了 Git 日常使用中最常用的命令,适合初学者和日常查阅,如有错误,敬请指正,谢谢! ☁️ Git 使用流程入门(从 pull 和 push 开始) …...
AI、机器学习、深度学习:一文厘清三者核心区别与联系
AI、机器学习、深度学习:一文厘清三者核心区别与联系 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 前言 在人工智能技术席卷全球的今天&…...
《数字藏品社交化破局:React Native与Flutter的创新实践指南》
NFT,这种非同质化代币,赋予了数字资产独一无二的身份标识,从数字艺术作品到限量版虚拟物品,每一件NFT数字藏品都承载着独特的价值与意义。当React Native和Flutter这两大跨平台开发框架遇上NFT数字藏品,一场技术与创意…...
工业操作系统核心技术揭秘
摘要 随着工业 4.0 与智能制造的深入推进,工业操作系统作为工业数字化转型的核心支撑,其技术发展备受关注。本文深入剖析工业操作系统的核心技术,包括实时性保障机制、硬件抽象层设计、多任务管理策略等,结合技术原理与实际应用场…...
Python logging模块使用指南
Python 的 logging 模块是一个灵活且强大的日志记录工具,广泛应用于应用程序的调试、运行监控和问题排查。它提供了丰富的功能,包括多级日志记录、多种输出方式、灵活的格式配置等。以下是详细介绍: 一、为什么使用 logging 模块?…...
沃伦森智能无功补偿系统解决电力电容器频繁投切的隐患
在现代电力系统中,无功补偿设备的稳定运行直接影响电网质量。然而,电力电容器的频繁投切问题长期存在,如同电网的“慢性病”,不仅加速设备老化,还可能引发系统性风险。作为电力电子领域的领军企业,沃伦森电…...
【HarmonyOS 5】鸿蒙mPaaS详解
【HarmonyOS 5】鸿蒙mPaaS详解 一、mPaaS是什么? mPaaS 是 Mobile Platform as a Service 的缩写,即移动开发平台。 蚂蚁移动开发平台mPaaS ,融合了支付宝科技能力,可以为移动应用开发、测试、运营及运维提供云到端的一站式解决…...
PyTorch中.item()函数:提取单元素张量值
PyTorch中,.item()函数是什么 在PyTorch代码中,.item() 主要用于从一个只包含单个元素的张量(Tensor)中提取出对应的Python标量值 ,具体作用和使用场景如下: 作用 获取数值:当通过计算得到一个张量,且该张量仅包含一个元素时,使用 .item() 方法可以方便地将这个元素…...
PyTorch LSTM练习案例:股票成交量趋势预测
文章目录 案例介绍源码地址代码实现导入相关库数据获取和处理搭建LSTM模型训练模型测试模型绘制折线图主函数 绘制结果 案例介绍 本例使用长短期记忆网络模型对上海证券交易所工商银行的股票成交量做一个趋势预测,这样可以更好地掌握股票买卖点,从而提高…...
ARM A64 LDR指令
ARM A64 LDR指令 1 LDR (immediate)1.1 Post-index1.2 Pre-index1.3 Unsigned offset 2 LDR (literal)3 LDR (register)4 其他LDR指令变体4.1 LDRB (immediate)4.1.1 Post-index4.1.2 Pre-index4.1.3 Unsigned offset 4.2 LDRB (register)4.3 LDRH (immediate)4.3.1 Post-index…...
一些问题杂记
1. 在 SSH 会话/bash中仅使用cat命令查看文件后使用umount命令提示挂载点繁忙,lsof命令查看是bash有占用,但是并没有打开文件之类的情况 原因:当前工作目录仍在挂载点内,使用cat查看文件时,可能当前工作目录ÿ…...
【OpenGL学习】(一)创建窗口
文章目录 【OpenGL】(一)创建窗口 【OpenGL】(一)创建窗口 GLFW OpenGL 本身只是一套图形渲染 API,不提供窗口创建、上下文管理或输入处理的功能。 GLFW 是一个支持创建窗口、处理键盘鼠标输入和管理 OpenGL 上下文的…...
RTSP 播放器技术探究:架构、挑战与落地实践
RTSP 播放器为什么至今无法被淘汰? 在实时视频传输领域,RTSP(Real-Time Streaming Protocol)作为最基础、最常见的协议之一,至今依然被广泛用于监控设备、IP Camera、视频服务器等设备中。然而,要构建一个稳…...
【问题记录】08 MAC电脑,安装HP打印机驱动,提示:此更新需要macOS版本15.0或更低版本
问题描述: MAC电脑,升级了新系统之后(v15.4.1)。 这时,安装惠普(HP)打印机驱动,提示:This update requires macOS version 15.0 or earlier(此更新需要macOS…...
场景新零售:基于开源AI大模型AI智能名片S2B2C商城小程序源码的商业本质回归与创新
摘要:本文聚焦场景新零售,探讨在新生代消费群体推动下传统零售模式的创新升级。通过分析新生代消费群体的特点以及场景新零售的发展趋势,阐述开源AI大模型AI智能名片S2B2C商城小程序源码在场景新零售中的应用优势,包括精准营销、供…...
16.2 VDMA视频转发实验之模拟源
文章目录 1 实验任务2 系统框图3 硬件设计3.1 IP核配置3.2 注意事项3.3 自定义IP核源码 1 实验任务 基于14.1,相较于16.1,使用自定义IP核vid_gen_motion替换Xilinx TPG IP核。 2 系统框图 基于14.1,添加自定义IP核vid_gen_motion作为视频源…...
PADS 9.5安装教程
1.安装包 https://pan.baidu.com/s/1bt6vE3y8VEmlFwJfoV32nA?pwdj2cg 2.PADS 9.5安装教程 PADS 9.5安装教程(Windows11、超详细版)_pads9.5-CSDN博客 3.出现的问题 1.打开无法使用鼠标滚轮 Win10 pads卡死问题解决,输入法的兼容性问…...
趣味编程:钟表
目录 1. 效果展示 2. 源码展示 3. 逻辑概述 3.1 表针绘制函数(DrawHand) 3.2 表盘绘制函数 3.3 主程序逻辑 4. 小结 概述:本篇博客主要介绍简易钟表的绘制。 1. 效果展示 该钟表会随着系统的时间变化而变化,动态的效…...
.NET 通过命令行解密web.config配置
在.NET应用系统中,保护数据库连接字符串的安全性至关重要。.NET 提供了一种通过 DataProtectionConfigurationProvider 加密连接字符串的方法,以防止敏感数据泄露。然而,在内网信息收集阶段,攻击者只需在目标主机上运行aspnet_regiis.exe这个命令行工具即可完成解密,获取数…...
【MySQL】多表连接查询
个人主页:Guiat 归属专栏:MySQL 文章目录 1. 多表连接查询概述1.1 连接查询的作用1.2 MySQL支持的连接类型 2. 内连接 (INNER JOIN)2.1 内连接的特点2.2 内连接语法2.3 内连接实例2.4 多表内连接 3. 左外连接 (LEFT JOIN)3.1 左外连接的特点3.2 左外连接…...
【AI论文】用于评估和改进大型语言模型中指令跟踪的多维约束框架
摘要:接下来的指令评估了大型语言模型(LLMs)生成符合用户定义约束的输出的能力。 然而,现有的基准测试通常依赖于模板化的约束提示,缺乏现实使用的多样性,并限制了细粒度的性能评估。 为了填补这一空白&…...
应用BERT-GCN跨模态情绪分析:贸易缓和与金价波动的AI归因
本文运用AI量化分析框架,结合市场情绪因子、宏观经济指标及技术面信号,对黄金与美元指数的联动关系进行解析,揭示本轮贵金属回调的深层驱动因素。 周三,现货黄金价格单日跌幅达2.1%,盘中触及3167.94美元/盎司关键价位&…...
低成本高效图像生成:GPUGeek和ComfyUI的强强联合
一、时代背景 在如今的数字化时代,图像生成技术正不断发展和演变,尤其是在人工智能领域。无论是游戏开发、虚拟现实,还是设计创意,图像生成已成为许多应用的核心技术之一。然而,随着图像质量需求的提升,生成…...
React 第四十二节 Router 中useLoaderData的用途详解
一、前言 useLoaderData,用于在组件中获取路由预加载的数据。它通常与路由配置中的 loader 函数配合使用,用于在页面渲染前异步获取数据(如 API 请求),并将数据直接注入组件,从而简化数据流管理。 二、us…...
【NLP 74、最强提示词工程 Prompt Engineering 从理论到实战案例】
一定要拼尽全力,才能看起来毫不费劲 —— 25.5.15 一、提示词工程 1.提示词工程介绍 Ⅰ、什么是提示词 所谓的提示词其实就是一个提供给模型的文本片段,用于指导模型生成特定的输出或回答。提示词的目的是为模型提供一个任务的上下文,以便模…...
GPUGeek云平台实战:DeepSeek-R1-70B大语言模型一站式部署
随着人工智能技术的迅猛发展,特别是在自然语言处理领域,大型语言模型如DeepSeek-R1-70B的出现,推动了各行各业的变革。为了应对这些庞大模型的计算需求,云计算平台的普及成为了关键,特别是基于GPU加速的云平台…...
【抽丝剥茧知识讲解】引入mybtis-plus后,mapper实现方式
目录 前言一、传统 Mapper 接口方式二、继承 BaseMapper 的方式三、自定义通用 Mapper 的方式四、使用 MyBatis-Plus 的 ActiveRecord 模式五、使用 MyBatis-Plus 的 IService 接口六、使用建议 前言 mapper文件,作为Mybatis框架中定义SQL语句和映射关系的配置文件&…...
AI浪潮:开启科技新纪元
AI 的多面应用 AI 的影响力早已突破实验室的围墙,在众多领域落地生根,成为推动行业变革的重要力量。 在医疗领域,AI 宛如一位不知疲倦的助手,助力医生提升诊疗效率与准确性。通过对海量医学影像的深度学习,AI 能够快…...
制造业工厂的三大核心系统:ERP+PLM+MES
对于一家制造业工厂来说,要实现数字化转型,哪几个系统最重要?答案是:ERP,PLM和MES这三个核心系统最为重要!本文就为你快速地概览地介绍一下这三个系统 以及 它们之间的关联关系。 ERP:企业资源计划 ERP的全称是Enterprise Resource Planning,即企业资源计划系统。 它…...
驱动-定时-秒-字符设备
文章目录 目的相关资料参考实验驱动程序-timer_dev.c编译文件-Makefile测试程序-timer.c分析 加载驱动-运行测试程序总结 目的 通过定时器timer_list、字符设备、规避竞争关系-原子操作,综合运用 实现一个程序,加深之前知识的理解。 实现字符设备驱动框…...
(面试)Handler消息处理机制原理
Handler是用于实现线程间通信和任务调度的一种机(Handler、 Looper、MessageQueue、 Message)。Handler 允许线程间发送Message或Runnable对象进行通信。在Android中UI修改只能通过UI Thread,子线程不能更新UI。如果子线程想更新UI࿰…...
WebRTC 通话原理:从协商到通信
在实时音视频通信领域,WebRTC(Web Real-Time Communication)凭借其开源、无需插件且能在浏览器中直接实现高质量通信的特性,成为开发者的热门选择。本文将深入解析 WebRTC 通话原理,涵盖媒体协商、网络协商、网络穿越&…...
InforSuite AS 可以发布django和vue项目是否可行
InforSuite AS 是浪潮推出的企业级中间件平台,主要用于应用集成、流程管理、数据交换等场景,其核心功能更偏向于 Java EE 应用的部署和管理(如支持 WAR/EAR 包)。关于能否直接发布 Django(Python 框架)和 V…...
【中级软件设计师】网络攻击(附软考真题)
【中级软件设计师】网络攻击(附软考真题) 目录 【中级软件设计师】网络攻击(附软考真题)一、历年真题二、考点:网络攻击1、拒绝服务攻击(DoS攻击)2、重放攻击3、特洛伊木马4、网络监听5、SQL注入…...
CSS图片垂直居中问题解决方案
在 CSS 中,使用 vertical-align: middle 导致图片略微向下偏移的现象,本质上是由于 行内元素的基线对齐规则 和 父容器上下文环境 共同作用的结果。以下是具体原因和解决方案: 原因详解 1. vertical-align: middle 的真实含义 该属性 不会让…...
P1601 A+B Problem(高精)
题目描述 高精度加法,相当于 ab problem,不用考虑负数。 输入格式 分两行输入。a,b≤10500。 输出格式 输出只有一行,代表 ab 的值。 输入输出样例 输入 1 1 输出 2 输入 1001 9099 输出 10100 说明/提示 20% 的测试数据…...
鸿蒙OSUniApp实现个性化的搜索框与搜索历史记录#三方框架 #Uniapp
使用UniApp实现个性化的搜索框与搜索历史记录 在移动端应用开发中,搜索功能几乎是标配,而一个好的搜索体验不仅仅是功能的实现,更是用户留存的关键。本文将分享如何在UniApp框架下打造一个既美观又实用的搜索框,并实现搜索历史记录…...