【C++笔记】红黑树封装map和set深度剖析
【C++笔记】红黑树封装map和set深度剖析
🔥个人主页:大白的编程日记
🔥专栏:C++笔记
文章目录
- 【C++笔记】红黑树封装map和set深度剖析
- 前言
- 一. 源码及框架分析
- 1.1 源码框架分析
- 二. 模拟实现map和set
- 2.1封装map和set
- 三.迭代器
- 3.1思路分析
- 3.2 代码实现
- 四.operator[]
- 4.1思路分析
- 五.源码
- 后言
前言
哈喽,各位小伙伴大家好!上期我们讲了红黑树。今天我们来讲一下用红黑树封装map和set。话不多说,我们进入正题!向大厂冲锋
一. 源码及框架分析
我们看一下源码是如何实现红黑树封装map和set。
参考SGI-STL30版本源代码,map和set的源代码在map/set/stl_map.h/stl_set.h/stl_tree.h等几个头文件中。
// set
#ifndef __SGI_STL_INTERNAL_TREE_H
#include <stl_tree.h>
#endif
#include <stl_set.h>
#include <stl_multiset.h>
// map
#ifndef __SGI_STL_INTERNAL_TREE_H
#include <stl_tree.h>
#endif
#include <stl_map.h>
#include <stl_multimap.h>
// stl_set.h
template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set {
public:// typedefs:typedef Key key_type;typedef Key value_type;
private:typedef rb_tree<key_type, value_type,identity<value_type>, key_compare, Alloc> rep_type;rep_type t; // red-black tree representing set
};
// stl_map.h
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map {
public:// typedefs:typedef Key key_type;typedef T mapped_type;typedef pair<const Key, T> value_type;
private:
typedef rb_tree<key_type, value_type,
select1st<value_type>, key_compare, Alloc> rep_type;
rep_type t; // red-black tree representing map
};
// stl_tree.h
struct __rb_tree_node_base
{
typedef __rb_tree_color_type color_type;
typedef __rb_tree_node_base* base_ptr;
color_type color;
base_ptr parent;
base_ptr left;
base_ptr right;
};
// stl_tree.h
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc= alloc>
class rb_tree {
protected:typedef void* void_pointer;typedef __rb_tree_node_base* base_ptr;typedef __rb_tree_node<Value> rb_tree_node;typedef rb_tree_node* link_type;typedef Key key_type;typedef Value value_type;
public:// insert⽤的是第⼆个模板参数左形参pair<iterator, bool> insert_unique(const value_type& x);// erase和find⽤第⼀个模板参数做形参size_type erase(const key_type& x);iterator find(const key_type& x);
protected:size_type node_count; // keeps track of size of treelink_type header;
};
template <class Value>
struct __rb_tree_node : public __rb_tree_node_base
{
typedef __rb_tree_node<Value>* link_type;
Value value_field;
};
1.1 源码框架分析
- 通过下图对框架的分析,我们可以看到源码中rb_tree用了⼀个巧妙的泛型思想实现,rb_tree是实现key的搜索场景,还是key/value的搜索场景不是直接写死的,而是由第⼆个模板参数Value决定_rb_tree_node中存储的数据类型。
- set实例化rb_tree时第二个模板参数给的是key,map实例化rb_tree时第二个模板参数给的是pair<const key, T>,这样⼀颗红黑树既可以实现key搜索场景的set,也可以实现key/value搜索场景的map。
- 要注意一下,源码里面模板参数是用T代表value,而内部写的value_type不是我们我们日常key/value场景中说的value,源码中的value_type反而是红黑树结点中存储的真实的数据的类型。
- rb_tree第二个模板参数Value已经控制了红黑树结点中存储的数据类型,为什么还要传第一个模板参数Key呢?尤其是set,两个模板参数是⼀样的,这是很多同学这时的⼀个疑问。要注意的是对于map和set,find/erase时的函数参数都是Key,所以第⼀个模板参数是传给find/erase等函数做形参的类型的。对于set而言两个参数是⼀样的,但是对于map而言就完全不一样了,map insert的是pair对象,但是find和ease的是Key对象。
所以我们可以通过模版参数来控制红黑树底层的结构。
所以不用实现两颗红黑树,但是本质还是编译器根据模版参数生成两颗不同的红黑树。
二. 模拟实现map和set
这里借鉴源码的底层实现。
我们也自己模拟实现出我们的mymap和myset.
2.1封装map和set
- 参考源码框架,map和set复用之前我们实现的红黑树。
- 我们这里相比源码调整⼀下,key参数就用K,value参数就用V,红黑树中的数据类型,我们使用T。
- 其次因为RBTree实现了泛型不知道T参数导致是K,还是pair<K, V>,那么insert内部进行插入逻辑比较时,就没办法进行比较,因为pair的默认支持的是key和value⼀起参与比较,我们需要时的任何时候只比较key,所以我们在map和set层分别实现⼀个MapKeyOfT和SetKeyOfT的仿函数传给RBTree的KeyOfT,然后RBTree中通过KeyOfT仿函数取出T类型对象中的key,再进行比较,具体细节参考如下代码实现。
set.h:
template<class k>
class set
{
public:struct SetKeyofT{const k& operator()(const k& key){return key;}};bool insert(const k& kv){return _t.Insert(kv);}
private:qcj::RBTree<k, const k, SetKeyofT> _t;
};
map.h:
template<class k,class v>
class map
{
public:struct MapKeyofT{const k& operator()(const pair<k, v>& key){return key.first;}};bool insert(const pair<k, v>& kv) {return _t.Insert(kv);}
private:qcj::RBTree<k, pair< const k, v>, MapKeyofT> _t;
};
insert:
bool Insert(const T& x)
{if (_root == nullptr)//插入根节点{_root = new node(x);_root->col = BLACK;return true;};node* cur = _root;node* parent = nullptr;//保留父亲节点KeyofT kot;while (cur){/*介质不冗余*/if (kot(x) < kot(cur->_date)){parent = cur;cur = cur->left;}else if (kot(x) > kot(cur->_date)){parent = cur;cur = cur->right;}else{return false;}}cur = new node(x);cur->col = RED;if (kot(x) > kot(parent->_date)){parent->right = cur;}else//相等插入左子树{parent->left = cur;}cur->parent = parent;while (parent&&parent->parent&&parent->col == RED){node* grandfather = parent->parent;if (parent == grandfather->left){node* uncle = grandfather->right;// g// p u// c c//u存在且为红if (uncle&&uncle->col==RED){parent->col = uncle->col=BLACK;grandfather->col = RED;cur = grandfather;parent = cur->parent;}//u不存在或存在为黑else{// g// p // cif (cur == parent->left){RoRateR(grandfather);parent->col = BLACK;grandfather->col = RED;}// g// p // celse{RoRateL(parent);RoRateR(grandfather);cur->col = BLACK;grandfather->col = RED;}break;}}else{node* uncle = grandfather->left;// g// u p // c c//u存在且为红if (uncle && uncle->col == RED){parent->col = uncle->col = BLACK;grandfather->col = RED;cur = grandfather;parent = cur->parent;}//u不存在或存在为黑else{// g// p // cif (cur == parent->right){RoRateL(grandfather);parent->col = BLACK;grandfather->col = RED;}// g// p // celse{RoRateR(parent);RoRateL(grandfather);cur->col = BLACK;grandfather->col = RED;}break;}}}_root->col = BLACK;//循环结束把根变黑return true;
}
find:
node* Find(const k& x)
{node* ret = nullptr;node* cur = _root;while (cur){if (x < kot(cur)){cur = cur->left;}else if (x > kot(cur)){cur = cur->right;}else{ret = cur;//保留当前节点cur = cur->left;//继续向左子树查找中序的第一个}}return ret;
}
这里通过仿函数就取出key控制了比较逻辑。
三.迭代器
3.1思路分析
- operator++
- operator- -
- 迭代器的key修改问题
如果我们这样实现的迭代器是可以修改的key的。
但是红黑树的key是不能被修改的。那怎么办呢?
我们只需要把红黑树的第二个模版参数的key改为
const key即可这样迭代器的模版参数T的key也是const的了
set的iterator也不支持修改,我们把set的第⼆个模板参数改成const K即可,
qcj::RBTree<k, pair< const k, v>, MapKeyofT> _t;
qcj::RBTree<k, const k, SetKeyofT> _t;
-
对比库里的迭代器
为了实现反向迭代器我们可以在operator- -多加一个判断。
同时还需要在迭代器里面加一个_root节点
-
运算符重载
运算符重载比较简单具体参考下面的代码
3.2 代码实现
template<class T,class Ref,class Ptr>
struct RBTreeIteraor
{using node= RBNode<T>;using self= RBTreeIteraor< T, Ref, Ptr >;node* _node;node* _root;RBTreeIteraor(node* Node,node* root):_node(Node),_root(root){}self& operator++(){if (_node == nullptr){node* cur = _root;while (cur->right){cur = cur->right;}}else if (_node->right!=nullptr){node* cur = _node->right;while (cur->left){cur = cur->left;}_node = cur;}else{node* parent = _node->parent;while (parent&&_node != parent->left){_node = parent;parent = _node->parent;}_node = parent;}return *this;}self& operator--(){if (_node == nullptr){node* cur = _root;while (cur->right){cur = cur->right;}_node = cur;}else if (_node->left != nullptr){node* cur = _node->left;while (cur->right){cur = cur->right;}_node = cur;}else{node* parent = _node->parent;while (parent && _node != parent->right){_node = parent;parent = _node->parent;}_node = parent;}return *this;}Ref operator*(){return _node->_date;}Ptr operator->(){return &_node->_date;}bool operator==(const self& tmp) const{return _node==tmp._node;}bool operator!=(const self& tmp) const{return _node != tmp._node;}
};
四.operator[]
4.1思路分析
对于map我们还需要支持operator[]。
对于operator[]我们前面已经讲过底层实现了。
参考博文:map的operator[]底层剖析
主要就是insert来支持的。改一下返回值即可。
让insert返回迭代器和bool的pair即可。
返回insert迭代器的second也就是value即可。
v& operator[](const k& key)
{pair<iterator, bool> ret = _t.Insert(make_pair(key, v()));return ret.first->second;
}
五.源码
- set.h
#pragma once
#include"RBTree.h"
namespace qcj
{template<class k>class set{public:struct SetKeyofT{const k& operator()(const k& key){return key;}};public:typedef typename RBTree<k, const k, SetKeyofT>::Iteratoriterator;typedef typename RBTree<k, const k, SetKeyofT>::Const_Iteratorconst_iterator;iterator begin(){return _t.Begin();}iterator end(){return _t.End();}const_iterator begin() const{return _t.Begin();}const_iterator end() const{return _t.End();}pair<iterator, bool> insert(const k& kv){return _t.Insert(kv);}iterator find(const k& key){return _t.find(key);}private:qcj::RBTree<k, const k, SetKeyofT> _t;};void Print(const set<int>& s){set<int>::iterator it = s.end();while (it != s.begin()){--it;// 不⽀持修改//*it += 2;cout << *it << " ";}cout << endl;}void test_set(){set<int> s;int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };for (auto e : a){s.insert(e);}for (auto e : s){e += 1;cout << e << " ";}cout << endl;}}
- map.h
#pragma once
#include"RBTree.h"
namespace qcj
{template<class k,class v>class map{public:struct MapKeyofT{const k& operator()(const pair<k, v>& key){return key.first;}};public:typedef typename RBTree<k, pair<const k, v>, MapKeyofT>::Iteratoriterator;typedef typename RBTree<k, pair<const k, v>, MapKeyofT>::Const_Iteratorconst_iterator;iterator begin(){return _t.Begin();}iterator end(){return _t.End();}const_iterator begin() const{return _t.Begin();}const_iterator end() const{return _t.End();}pair<iterator, bool> insert(const pair<k, v>& kv) {return _t.Insert(kv);}iterator find(const k& key){return _t.find(key);}v& operator[](const k& key){pair<iterator, bool> ret = _t.Insert(make_pair(key, v()));return ret.first->second;}private:qcj::RBTree<k, pair< const k, v>, MapKeyofT> _t;};void test_map(){map<int,int> dict;dict.insert({1,1});dict.insert({2,2 });dict.insert({3,3 });dict.insert({ 4,4 });dict.insert({ 5,5 });dict.insert({ 6,6 });map<int,int>::iterator it = dict.end();while (it != dict.begin()){--it;// 不能修改first,可以修改second//it->first += 'x';it->second += 1;cout << it->first << ":" << it->second << endl;}cout << endl;}
}
- RBTree.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace qcj
{enum coloros{RED,BLACK};template<class T>struct RBNode{using node= RBNode<T>;T _date;node* left;//左节点node* right;//右节点node* parent;//父亲节点coloros col;//颜色RBNode(const T& date):_date(date), left(nullptr), right(nullptr), parent(nullptr){}};template<class T,class Ref,class Ptr>struct RBTreeIteraor{using node= RBNode<T>;using self= RBTreeIteraor< T, Ref, Ptr >;node* _node;node* _root;RBTreeIteraor(node* Node,node* root):_node(Node),_root(root){}self& operator++(){if (_node == nullptr){node* cur = _root;while (cur->right){cur = cur->right;}}else if (_node->right!=nullptr){node* cur = _node->right;while (cur->left){cur = cur->left;}_node = cur;}else{node* parent = _node->parent;while (parent&&_node != parent->left){_node = parent;parent = _node->parent;}_node = parent;}return *this;}self& operator--(){if (_node == nullptr){node* cur = _root;while (cur->right){cur = cur->right;}_node = cur;}else if (_node->left != nullptr){node* cur = _node->left;while (cur->right){cur = cur->right;}_node = cur;}else{node* parent = _node->parent;while (parent && _node != parent->right){_node = parent;parent = _node->parent;}_node = parent;}return *this;}Ref operator*(){return _node->_date;}Ptr operator->(){return &_node->_date;}bool operator==(const self& tmp) const{return _node==tmp._node;}bool operator!=(const self& tmp) const{return _node != tmp._node;}};template<class k, class T, class KeyofT>class RBTree{using node = RBNode<T>;public:RBTree() = default;using Iterator = RBTreeIteraor<T, T&, T*>;using Const_Iterator = RBTreeIteraor<T, const T&, const T*>;Iterator Begin(){node* cur = _root;while (cur&&cur->left){cur = cur->left;}return Iterator(cur,_root );}Iterator End(){return Iterator(nullptr,_root);}Const_Iterator Begin() const{node* cur = _root;while (cur&&cur->left){cur = cur->left;}return { cur,_root };}Const_Iterator End() const{return { nullptr,_root };}void Destory(const node* root){if (root == nullptr){return;}Destory(root->left);Destory(root->right);delete root;}~RBTree(){Destory(_root);_root = nullptr;}RBTree<k,T,KeyofT>& operator = (RBTree<k, T, KeyofT> tmp){swap(_root, tmp._root);return *this;}RBTree(const RBTree<k, T, KeyofT>& x){_root = Copy(x._root,nullptr);}node* Copy(node* x,node* parent){if (x == nullptr){return x;}node* root = new node(x->_date);root->parent = parent;root->left = Copy(x->left,root);root->right = Copy(x->right,root);return root;}void RoRateR(node* parent)//右单旋{node* subL = parent->left;node* subLR = subL->right;node* pparnet = parent->parent;parent->left = subLR;if (subLR){subLR->parent = parent;//修改父节点}subL->right = parent;parent->parent = subL;if (pparnet == nullptr)//parent就是根节点{_root = subL;subL->parent = nullptr;}else{if (pparnet->left == parent)//确定parent节点是左还是右{pparnet->left = subL;}else{pparnet->right = subL;}subL->parent = pparnet;//修改父节点}}void RoRateL(node* parent)//左单旋{node* subR = parent->right;node* subRL = subR->left;node* pparnet = parent->parent;parent->right = subRL;if (subRL)//防止subRL为空{subRL->parent = parent;//修改父节点}subR->left = parent;parent->parent = subR;if (pparnet == nullptr)//parent就是根节点{_root = subR;subR->parent = nullptr;}else{if (pparnet->left == parent)//确定parent节点是左还是右{pparnet->left = subR;}else{pparnet->right = subR;}subR->parent = pparnet;//修改父节点}}pair<Iterator,bool> Insert(const T& x) {if (_root == nullptr)//插入根节点{_root = new node(x);_root->col = BLACK;return make_pair(Iterator(_root, _root), true);};node* cur = _root;node* parent = nullptr;//保留父亲节点KeyofT kot;while (cur){/*介质不冗余*/if (kot(x) < kot(cur->_date)){parent = cur;cur = cur->left;}else if (kot(x) > kot(cur->_date)){parent = cur;cur = cur->right;}else{return make_pair(Iterator(cur, _root), true);}}cur = new node(x);cur->col = RED;if (kot(x) > kot(parent->_date)){parent->right = cur;}else//相等插入左子树{parent->left = cur;}cur->parent = parent;while (parent&&parent->parent&&parent->col == RED){node* grandfather = parent->parent;if (parent == grandfather->left){node* uncle = grandfather->right;// g// p u// c c//u存在且为红if (uncle&&uncle->col==RED){parent->col = uncle->col=BLACK;grandfather->col = RED;cur = grandfather;parent = cur->parent;}//u不存在或存在为黑else{// g// p // cif (cur == parent->left){RoRateR(grandfather);parent->col = BLACK;grandfather->col = RED;}// g// p // celse{RoRateL(parent);RoRateR(grandfather);cur->col = BLACK;grandfather->col = RED;}break;}}else{node* uncle = grandfather->left;// g// u p // c c//u存在且为红if (uncle && uncle->col == RED){parent->col = uncle->col = BLACK;grandfather->col = RED;cur = grandfather;parent = cur->parent;}//u不存在或存在为黑else{// g// p // cif (cur == parent->right){RoRateL(grandfather);parent->col = BLACK;grandfather->col = RED;}// g// p // celse{RoRateR(parent);RoRateL(grandfather);cur->col = BLACK;grandfather->col = RED;}break;}}}_root->col = BLACK;//循环结束把根变黑return make_pair(Iterator(cur, _root), true);}bool check(node* cur,size_t tmp,size_t sum){if (cur == nullptr){if (tmp != sum){cout << "存在黑色结点的数量不相等的路径" << endl;return false;}return true;}if (cur->col == RED){if (cur->parent->col == RED){cout << cur->_key << ":" << "存在连续红节点" << endl;return false;}}else{sum++;}return check(cur->left, tmp, sum) && check(cur->right, tmp, sum);}bool ISRBTree(){return _ISRBTree(_root);}bool _ISRBTree(node* cur){if (cur == nullptr){return true;}if (cur->col == RED){return false;}size_t t = 0;while (cur){if (cur->col == BLACK){t++;}cur = cur->left;}return check(_root,t,0);}node* Find(const k& x){node* ret = nullptr;node* cur = _root;while (cur){if (x < kot(cur)){cur = cur->left;}else if (x > kot(cur)){cur = cur->right;}else{ret = cur;//保留当前节点cur = cur->left;//继续向左子树查找中序的第一个}}return ret;}void Inorder(){_Inorder(_root);cout << endl;}bool IsBalanceTree(){return _IsBalanceTree(_root);}void _Inorder(const node* root){if (root == nullptr){return;}_Inorder(root->left);cout << root->_key << ":" << root->_value << endl;_Inorder(root->right);}size_t Size(){return _Size(_root);}size_t _Size(const node* parent){if (parent){return 1 + _Size(parent->left) + _Size(parent->right);}else{return 0;}}size_t Height(){return _Height(_root);}size_t _Height(const node* parent){if (parent){return 1 + max(_Height(parent->left), _Height(parent->right));}else{return 0;}}bool Empty(){return _root == nullptr;}private:node* _root = nullptr;};
}
后言
这就是红黑树封装map和set深度剖析。大家自己好好消化!今天就分享到这!感谢各位的耐心垂阅!咱们下期见!拜拜~
相关文章:

【C++笔记】红黑树封装map和set深度剖析
【C笔记】红黑树封装map和set深度剖析 🔥个人主页:大白的编程日记 🔥专栏:C笔记 文章目录 【C笔记】红黑树封装map和set深度剖析前言一. 源码及框架分析1.1 源码框架分析 二. 模拟实现map和set2.1封装map和set 三.迭代器3.1思路…...

4.若依 BaseController
若依的BaseController是其他所有Controller的基类,一起来看下BaseController定义了什么 1. 定义请求返回内容的格式 code/msg/data 返回数据格式不是必须是AjaxResult,开发者可以自定义返回格式,注意与前端取值方式一致即可。 2. 获取调用…...
vue项目配置多语言
本文详细介绍如何在 Vue 项目中集成 vue-i18n 和 Element-UI ,实现多语言切换;首先通过 npm 安装 vue-i18n 和相关语言包,接着在配置文件中设置中文和英文的语言信息;最后在 main.js 中导入并挂载多语言实例,实现切换地…...
数据可视化大屏设计与实现
本文将带你一步步了解如何使用 ECharts 实现一个数据可视化大屏,并且如何动态加载天气数据展示。通过整合 HTML、CSS、JavaScript 以及后端接口请求,我们可以构建一个响应式的数据可视化页面。 1. 页面结构介绍 在此例中,整个页面分为几个主…...

PDF文件提取开源工具调研总结
概述 PDF是一种日常工作中广泛使用的跨平台文档格式,常常包含丰富的内容:包括文本、图表、表格、公式、图像。在现代信息处理工作流中发挥了重要的作用,尤其是RAG项目中,通过将非结构化数据转化为结构化和可访问的信息࿰…...

多监控m3u8视频流,怎么获取每个监控的封面图(纯前端)
文章目录 1.背景2.问题分析3.解决方案3.1解决思路3.2解决过程3.2.1 封装播放组件3.2.2 隐形的视频div3.2.3 截取封面图 3.3 结束 1.背景 有这样一个需求: 给你一个监控列表,每页展示多个监控(至少12个,m3u8格式)&…...

【机器学习实战入门项目】使用深度学习创建您自己的表情符号
深度学习项目入门——让你更接近数据科学的梦想 表情符号或头像是表示非语言暗示的方式。这些暗示已成为在线聊天、产品评论、品牌情感等的重要组成部分。这也促使数据科学领域越来越多的研究致力于表情驱动的故事讲述。 随着计算机视觉和深度学习的进步,现在可以…...
技术洞察:C++在后端开发中的前沿趋势与社会影响
文章目录 引言C在后端开发中的前沿趋势1. 高性能计算的需求2. 微服务架构的兴起3. 跨平台开发的便利性 跨领域技术融合与创新实践1. C与人工智能的结合2. C与区块链技术的融合 C对社会与人文的影响1. 提升生产力与创新能力2. 促进技术教育与人才培养3. 技术与人文的深度融合 结…...

【人工智能 | 大数据】基于人工智能的大数据分析方法
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈智能大数据分析 ⌋ ⌋ ⌋ 智能大数据分析是指利用先进的技术和算法对大规模数据进行深入分析和挖掘,以提取有价值的信息和洞察。它结合了大数据技术、人工智能(AI)、机器学习(ML&a…...

数字经济时代下的创新探索与实践:以“开源AI智能名片2+1链动模式S2B2C商城小程序源码”为核心
摘要:在数字经济蓬勃发展的今天,中国作为全球数字经济的领航者,正以前所未有的速度推进“数字中国”建设。本文旨在探讨“开源AI智能名片21链动模式S2B2C商城小程序源码”在数字经济背景下的应用潜力与实践价值,从多个维度分析其对…...
【English-Book】Go in Action目录页翻译中文
第8页 内容 前言 xi 序言 xiii 致谢 xiv 关于本书 xvi 关于封面插图 xix 1 介绍 Go 1 1.1 用 Go 解决现代编程挑战 2 开发速度 3 • 并发 3 • Go 的类型系统 5 内存管理 7 1.2 你好,Go 7 介绍 Go 玩具 8 1.3 总结 8 2 Go 快速入门 9 2.1 程序架构 10 2.2 主包 …...

js: 区分后端返回数字是否为null、‘-’ 或正常number类型数字。
问: 这是我的代码<CountTo v-if!isNaN(Number(item.num))> <span v-else>{{item.num}}</span> 我希望不是null的时候走countTo,是null的时候直接<span>{{item.num}}</span>显示 回答: 最终结果: …...

网络变压器的分类
网络变压器是局域网(LAN)中各级网络设备中必备的元件。它们的主要功能是传输数据,增强信号,并提供电气隔离,以防雷保护和匹配阻抗。网络变压器也被称为数据泵或网络隔离变压器。它们广泛应用于网络交换机、路由器、网卡、集线器等设备中。 网…...

SUCTF-SU_BBRE-好久不见21
哈哈哈哈哈哈,,,,纯汇编有大佬用工具反编译成伪代码吗。。。 题解: 由function2处逻辑,解rc4得到第一段flag We1com3ToReWorld,正常输入下执行完function0,程序结束,cong…...

Python 实现 NLP 的完整流程
💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长…...

穷举vs暴搜vs深搜vs回溯vs剪枝系列一>N 皇后
题目: 解析: 1.决策树: 代码设计: 根据决策树剪枝设计: 代码: class Solution {private List<List<String>> ret;private char[][] path;private boolean[] checkdig1,checkdig2,checkco…...

JEL分类号
JEL分类系统,是美国经济学会“经济文献杂志”(《经济文献杂志》)所创立的对经济学文献的主题分类系统,并被现代西方经济学界广泛采用。 该分类方法主要采用开头的一个英文字母与随后的两位阿拉伯数字一起对经济学各部类进行“辞书式”编码分类。 https:…...
设计和优化用于 AR、HUD 和高级显示系统的表面浮雕光栅
表面浮雕光栅是许多光学系统中的关键组件,在控制增强现实 (AR) 显示器、平视显示器 (HUD) 和其他先进光子器件中的光传播方面发挥着关键作用。作为在这个领域工作的工程师和设计师,您了解针对特定应用优化这…...

【今日分享】人工智能加速发现能源新材料的结构与性能
人工智能与材料国际学术会议(ICAIM)workshop9是由来自宁夏大学材料与新能源学院副院长王海龙教授及马薇副教授、杜鑫老师组成,他们将以“人工智能加速发现新能源新材料的结构与性能”为主题开展研讨工作,欢迎对该主题感兴趣的专家学者携稿加入。 loadin…...
Boost Asio TCP异步服务端和客户端
服务端 消息分两次发送,第一次发送head,第二次发送body。接收也是先接收head,然后通过head结构中的body长度字段再接收body。 TcpServer.h #pragma once #include <atomic> #include <vector> #include <unordered_set> #…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...