封装红黑树实现map和set
" 喜欢了你十年,却用整个四月,编织了一个不爱你的谎言。 "
目录
1 源码及其框架分析
2 模拟实现map和set
2.1 实现出复用红黑树的框架
2.2 支持iterator迭代器的实现
2.2.1 代码实现++和--这两个运算符
2.3 map支持[ ]
Hello,大家好,前面我们已经学习了红黑树的底层结构,并且也已经知道了map和set的底层结构其实就是封装了一棵红黑树,但是如果大家了解过map和set的实参个数的话,会发现map需要我们传递2个参数,而set只需要我们传递1个参数,说到这里就有同学好奇了,set的实际传递参数的个数和红黑树所需要的参数个数明显不一致,这个要怎么封装呢?接下来,我就来为大家展示一下map和set如何封装红黑树。
1 源码及其框架分析
我们前面的一篇博客(下面有相应的链接1)讲解了关于红黑树的一些基本功能的实现及其具体得到一个内部结构,并且我们通过前面所学的知识可以得知,在前面还有一篇博客中所讲解的map和set这两个容器的底层(下面有相应的链接2)它其实就是封装了一棵红黑树,说到这里,就会有同学结合红黑树的内部结构以及map和set的内部结构,就会认为map和set的底层分别各自封装了一棵红黑树,在set中的节点存放的是key,而在map中的节点存放的是pair类类型的变量,但事实上并不是这样的,它们的底层共用的是同一颗红黑树,但是,是如何做到的呢?在这里,那接下来,我们就来结合截取出来的map和set的部分核心代码来看一下到底是如何做到的呢?
链接1:数据结构——红黑树的实现:
https://blog.csdn.net/2301_81390458/article/details/145192209?spm=1001.2014.3001.5502https://blog.csdn.net/2301_81390458/article/details/145192209?spm=1001.2014.3001.5502
链接2:map和set的使用,相信我,超简单的!:
map和set的使用,相信我,超简单的!-CSDN博客文章浏览阅读2.7k次,点赞189次,收藏152次。class set;//T是关键字类型,用来构造二叉搜索树的时候会用到;Compare是一个仿函数,默认set类的底层的那棵二叉搜索树是左边的关键字永远比根小,右边的关键字永远比根大;Alloc是一个内存池,我们现在不需要看这个参数。2>.set类默认要求T支持小于比较,如果不支持或者作者想按自己的需求走的话我们可以自行实现仿函数传给第二个模板参数。3>.set底层存储数据的内存是从空间配置器中申请的,如果需要我们可以自己实现内存池,传给第三个参数。4>.一般情况下,我们都不需要去传后两个模板参数。https://blog.csdn.net/2301_81390458/article/details/143649337?spm=1001.2014.3001.5502https://blog.csdn.net/2301_81390458/article/details/143649337?spm=1001.2014.3001.5502
在真正开始展示源代码之前,我们先来说一下我们前一篇博客中实现的那个红黑树的节点结构,我们所实现的节点中的元素是一个pair类类型的变量,这只是我们自主实现的,实际上红黑树的节点中存放的有可能不是pair类类型的变量,我们这里通过下列代码来分析:
为了方便大家使用代码观看,我将代码放在了下面:
template<class key, class Compare=Less<key>, class Alloc=alloc>//Compare为仿函数,后面会讲到它的作用;Alloc暂时先不讲,后面会讲到。
class set//set是key搜索场景,因此只需传1个模板参数。
{
public:typedef key key_type;typedef key value_type;//set是key场景,因此关键字就是要存储的数据,key_type和value_type表示的都是同一个类型。
private:typedef rb_tree<key_type, value_type, identity<value_type>, key_compare, Alloc> rep_type;key_type是关键字类型,//value_type是存储数据类型,它们是一样的,identity<value_type>、 key_compare、Alloc这几个类型具体是什么,我们先不管,对我们这里不会造成影响。rep_type t;//定义一棵红黑树。
};template<class key, class T,class Compare=Less<key>, class Alloc=alloc>//解释和set中的解释相同。
class map
{
public:typedef key key_type;typedef T mapped_type;//map是key_value搜索场景,关键字是用来构建红黑树的,且用于查找和删除的,T是此节点中真正存放的东西。typedef pair<const key, T> value_type;//map中的各个节点中存放的是一个pair类类型的变量,而这个变量中有关键字和存储内容。
private:typedef rb_tree<key_type, value_type, select1st<value_type>, key_campare, Alloc> rep_type;//和set中的解释相同。rep_type t;//定义一棵红黑树。
};template<class key,class value,class keyofvalue,class Compare=Less<key>, class Alloc=alloc>//这些具体是什么类型暂时先不做任何解释。
class re_tree
{
protected:typedef _rb_tree_node<value> re_tree_node;//...还有一些成员,由于我们这里所讲解的知识点没有多大的关系,因此就不用写了。
};template<class value>
struct _rb_tree_node:public _rb_tree_node_base//_rb_tree_node_base这个类中包含了一些基本变量,比如说左指针,右指针等等。
{typedef _rb_tree_node<value>* link_type;//为了方便表示指针。value value_field;
};
上述的代码只是源码的一部分,其实并不全(完整),我们在set中传给红黑树的第二个模板参数是key类型的,通过我们上述代码中_rb_tree_node这个类模板可知,源码中是将红黑树的节点构成了一个模板,是根据传过来的类型来确定这个节点中应该存放哪种类型的元素变量,set中传给红黑树的第二个参数是key类型的,那么实例化出来的红黑树的节点中存放的就是key类型的元素,因而可以实现出key的搜索场景;在map中传给红黑树的第二个参数是pair类类型的变量,那么实例化出来的红黑树的节点中所存放的就是pair类类型的变量,因而可以实现出key/value的搜索场景。
说到了这里,那么我们就已经讲明白了map和set中是如何对同一棵红黑树进行封装的,map和set的内部它们封装的其实都是同一棵红黑树,但是节点中所存放的数据类型是不同的,这样的话就又会产生一个问题,就是我们在插入节点时,要依靠关键字去找最适合的插入位置,如果是set,就直接使用节点中存储的数据去找,反之,我们还得到pair类类型的对象中去找first,也就是一个需要进行解引用操作才可以找到的关键字,一个不需要就可以直接找到,两种方式不能直接融合在一起,为此,这里就需要我们去通过仿函数去单独实现map和set各自的实现方式。(其实pair也支持比较,只不过它的比较使用first和second一起参与比较的,我们这里则是只想让first进行比较,second是不能参与比较的,因此不能用pair中自己实现的)
//找关键字(与上述代码相呼应)
//set
struct SetKeyOfT
{const key& operator()(const key& k){return k;}
};
//map
struct MapKeyOfT
{const key& operator()(conct pair<key, T>& kv){return kv.first;}
};
1>.通过上图对框架的分析可知,我们可以看到源码中rb_tree用了一个巧妙的泛型思想去实现,re_tree是实现key的搜索场景,还是key/value的搜索场景并不是直接写死的,而是由第二个模板参数value去决定_rb_tree_node中存储的数据类型的。
2>.要注意一下,源码里面的模板参数是用T代表的value,而内部写的value_type并不是我们日常的key/value场景中所说的value,源码中的value_type反而是红黑树节点中存储的真实的数据的类型。
3>.re_tree第二个模板参数value就已经控制了红黑树的节点中存储的数据类型,那么为什么还要传第一个模板参数key呢?尤其是set,两个参数都是一模一样的,这是很多同学的一个疑问。要注意的是对于map和set而言,find/erase时的函数参数都是key,所以第一个模板参数其实是传给find/erase等函数做形参的参数类型的。对于set而言两个参数都是一样的,但是对于map而言就完全不一样了,map中insert的对象是pair类类型的对象,但是find和erase的参数是key对象。
2 模拟实现map和set
2.1 实现出复用红黑树的框架
template<class K, class V>
class map
{struct MapKeyOfT{const K& operator()(conct pair<const K, V>& kv){return kv.first;}};
public://实现map的各个操作及其功能。
private:RBTree<K, pair<K, V>, MapKeyOfT> _t;//K前面加了一个const修饰,是因为K是关键字类型,而关键字是不允许随便更改的,因此,加上const修饰,防止有人恶意更改。
};
template<class K>
class set
{struct SetKeyOfT{const key& operator()(const key& k){return k;}};
public://实现set的各个操作及其功能。
private:RBTree<K, K, SetKeyOfT> _t;
};
enum colour
{RED,BLACK
};
template<class T>
struct RBTreeNode
{T _data;RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;colour _col;RBTreeNode(const T& data):_data(data),_left(nullptr),_right(nullptr)_parent(nullptr){ }
};
template<class K, class V, class KeyOfT>
class RBTree
{typedef RBTreeNode<V> node;node* _root = nullptr;
public://实现红黑树中的各种操作及其一些功能。
};
1>.以上的框架相较于源码来说,这里是进行了一下调整,key参数就使用K,value参数就使用V,红黑树中的数据类型,我们这里使用的是T。
2>.因为RBTree实现了泛式不知道T参数到底是K,还是pair<K,V>,那么insert的内部进行插入的逻辑比较时,就没有办法去比较,因为pair默认支持的是key和value一起比较,我们需要的是不管任何时候比较的都是key,这与我们需要的明显不符合,所以我们在map和set中分别实现了一个MapKeyOfT和SetKeyOfT的仿函数传给RBTree中的KeyOfT,然后RBTree中通过KeyOfT仿函数取出T类型的对象中的key,再去进行比较,就会达到我们想要的效果了。
2.2 支持iterator迭代器的实现
1>.iterator实现的大框架跟list中的迭代器的思路是一样的,用一个类去封装节点的指针,再通过重载运算符实现,迭代器就可以像指针一样去访问了。
2>.这里的难点是operator++和operator--的实现。之前使用部分,我们分析了map和set的迭代器走的是中序遍历,左子树->根节点->右子树,那么这样的话begin( )返回的就是中序的第一个节点的iterator,也就是指向10这个节点的迭代器。
3>.迭代器++的核心逻辑就是不看全局,只考虑当前中序局部要访问的下一个节点。
4>.迭代器++时,如果it指向的节点的右子树不为空的话,那么就说明当前的这个节点我们已经访问完了,要访问的下一个节点就是右子树的最左节点,所以我们这里直接去找右子树中的最左节点就可以了。
5>.如果当前的这个节点是父亲的左,那么根据中序左子树->根节点->右子树,那么下一个访问的节点就是当前节点的父亲;如上图所示,假如it此时指向25这个节点,在++之后,就指向30那个节点了。
6>.如果当前的这个节点是父亲的右,根据中序左子树->根节点->右子树的访问顺序,就当前节点所在的父亲的子树就访问完了,那么下一个要访问的需要往根的祖先中去找,直到找到孩子是父亲左的那个祖先就是中序遍历下一个要访问的节点。
7>.end( )该如何表示呢?如上图所示,当it指向50时,++it,50为40的右,40为30的右,30为18的右,18是根,它的父亲是空指针,到这里时,就说明我们没有找到那个孩子是父亲左的那个祖先,这时父亲就为空了,那么我们就把it中的节点指针置为空,用nullptr去充当end( ),需要注意的是STL源码中,红黑树是增加了一个哨兵位头节点作为end( ),这哨兵位头节点和根互为父亲,左指针指向的是最左节点,右指针指向的是最右节点。相比于我们用nullptr来作为end( ),差别其实并不大,他能顺序的,我们也能实现,而STL源码中之所以要在红黑树上外加上一个头节点,主要还是因为更加便利,在求begin( )和end( )时就不需要我们去遍历红黑树了,还有一个原因是end()没有为空的这一个情况,更安全。
8>.我们这里地迭代器--地实现跟++的思路是类似的,逻辑正好可以反过来,因为它访问的顺序是右子树->根节点->左子树。
9>.set的iterator不支持修改,因为set节点中存储的数据内容就是关键字,而通过我们前面的学习可知,关键字是不允许被改变的,为了防止用户在使用时随意修改,我们把set的第二个模板参数改成const K即可,即RETree<K,const K,SetKeyOf>;(上述代码段中的第29行代码)。
10>.map的iterator也不支持修改,准确的说,不允许修改key,允许修改value,我们把map的第二个模板参数pair中的第一个参数改成const K即可,即 RBTree<K, pair<const K, V> MapKeyOfT> _t;(上述代码段中第14行代码)。
2.2.1 代码实现++和--这两个运算符
我们这里的代码实现选择用我们所讲的这个逻辑来实现,也就是不加哨兵位的那个,之所以不使用库中实现的那样(加上哨兵位)主要是因为太麻烦了,比方说当我们插入一个节点时,要判断它是否是最左节点,是否是最右节点,这使得我们无时不刻都得去维护哨兵位的三个指针,如果真的使用这个方法的话,那么我们就要去修改一下前面所写的那个红黑树的插入部分的代码了,为了相适应,我们这里选择不用哨兵位去实现++和--操作符。
template<class T,class Ref,class Ptr>
struct RBTreeIterator
{typedef RBTreeNode<T> Node;typedef RBTreeIterator<T, Ref, Ptr> Self;node* _node;//通过我们前面的讲解可知,我们不难得知迭代器的内部其实就是封装了一个节点类型的指针。node* _root;//指向整棵红黑树的那个根节点,这里不方便讲解它为什么要存在的意义和作用,因此我们放到后面再讲。RBTreeIterator(Node*node,Node*root):_node(node),_root(root){ }Self& operator++(){if (_node->_right)//如果当前节点的右子树不为空的话,那么下一个要访问的节点就是当前节点的右子树中的最左节点。{Node* leftMost = _node->_right;while (leftMost->_left)//如果leftMost所指向的节点的左子树为空的话,则此时leftMost所指向的那个节点就是我们要找的那个最左节点,反之,就继续去左子树中寻找。{leftMost = leftMost->_left;}_node = leftMost;}else//否则,就说明我们下一个要访问的节点就是当前这个节点的祖宗中的其中一个,如果当前这个节点是父亲的左,那么,按照逻辑来说的话,下一个访问的节点是该节点的父亲节点,反之,说明当前节点的父亲节点所在的那棵子树我们因为已经全部访问完了,则要继续往祖宗节点中去找合适的节点,直到遇到这个节点是父亲的左或是parent为空时,就可以结束了,如果parent为空的话,就说明整棵红黑树全部都访问完了,直接返回空就可以了。{Node* cur = _node;//让cur去找下一个一个访问的节点。Node* parent = cur->_parent;while (parent&& cur = parent->_right)//如果parent不为空且当前节点不为parent的左,就说明我们还没有找到合适的节点,需要继续到上面去找。{cur = parent;parent = cur->_parent;}//出了循环之后,就说明找到了符合条件的节点了,就是parent指向的那个节点,我们这里可以不用判断parent为空的情况,因为如果出循环后parent为空的话,我们最后还是要让_node指向空,可以直接让其指向parent即可。_node = parent;}return *this;//返回的是迭代器。}Self& operator--(){//我们这里在写--操作符时,相较于++操作符来说,除了逻辑在这里是相反的以外,还要防止它是否为空,因为可能有人会从end()开始--,end()返回的是指向空的迭代器,--会导致编译器报错的。if (_node == nullptr)//如果_node为空,则说明当前的这个迭代器是指向红黑树遍历一次的最后一个位置的下一个位置,此时进行--操作的话,下一个访问的位置应该是整棵红黑树的最有节点。{Node* rightMost = _root;//现在就可以体现出_root这个变量的作用了,我们大家先想想,就是我们这个迭代器是作为一个单独的类域存在的,而我们前面所实现的set,也是作为一个单独的类域存在的,集体的一棵红黑树是在set类中搭建好的,而迭代器这个类是没有的,若想在迭代器类中也访问set类中的这棵红黑树,就只能传过来,因此我们才要在前面多加上一个_root成员变量,目的就是为了接收传过来的根节点。while (rightMost && rightMost->_right)//之所以要再加上一步判断rightMost为真,是为了防止空树的存在。{rightMost = rightMost->_right;}_node = rightMost;}//接下来,我们来顺着++操作符的逻辑逆一下就好了。else if (_node->_left)//根据右子树->根节点->左子树的访问顺序我们可知如果当前节点的左子树存在的话,那么下一个被访问的节点就是当前节点的左子树中的最右节点。{Node* rightMost = _node->_left;while (rightMost->_right){rightMost = rightMost->_left;}}else//就说明下一个要访问的节点是当前节点的祖宗中的某一个节点。{Node* cur = _node;Node* parent = _node->_parent;while (parent && cur == parent->_right){cur = parent;parent = cur->_parent;}_node = parent;}return *this;}Ref operator*(){reutrn _node->_data;}//...
};
2.3 map支持[ ]
map要支持[ ]主要需要修改insert返回值支持,修改RBTree中的insert的返回值为pair<iterator,bool> Insert(const T& data)
代码实现如下所示:
V& operator[](const K& key)
{pair<iterator, bool> ret = insert({ key,V() });return ret.first->second;//这里省略了一个"->"。
}
OK,今天我们就先讲到这里了,那么,我们下一篇再见,谢谢大家的支持!
相关文章:
封装红黑树实现map和set
" 喜欢了你十年,却用整个四月,编织了一个不爱你的谎言。 " 目录 1 源码及其框架分析 2 模拟实现map和set 2.1 实现出复用红黑树的框架 2.2 支持iterator迭代器的实现 2.2.1 代码实现和--这两个运算符 2.3 map支持[ ] Hello,大家…...
Redis进阶使用
在日常工作中,使用Redis有什么需要注意的? 设置合适的过期时间。尽量避免大key问题,避免用字符串存储过大的数据;避免集合的数据量太大,要定期清除。 常用的数据结构有哪些?用在什么地方? 按…...
【ISO 14229-1:2023 UDS诊断全量测试用例清单系列:第四节】
ISO 14229-1:2023 UDS诊断服务测试用例全解析(Read DTC Information0x19服务) 作者:车端域控测试工程师 更新日期:2025年2月13日 关键词:UDS诊断协议、0x19服务、DTC信息读取、ISO 14229-1:2023、ECU测试 一、服务功能…...
使用Node.js进行串口通信
目录 一、 安装 serialport 库二.、实现方法1.打开串口并配置参数2. 向串口传递信息3. 接收串口信息4. 处理错误5. 关闭串口6. 使用解析器7. 获取串口列表 三、 完整示例代码 一、 安装 serialport 库 首先,需要安装 serialport 库。可以通过 npm 安装:…...
vue3+elementplus新建项目
更新node.js和npm node.js官网更新指南 可以根据自己的操作系统进行选择 我的电脑操作系统是mac os所以我的步骤如下 # Download and install nvm: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash# in lieu of restarting the shell \. &…...
【网络安全 | 漏洞挖掘】跨子域账户合并导致的账户劫持与删除
未经许可,不得转载。 文章目录 概述正文漏洞成因概述 在对目标系统进行安全测试时,发现其运行着两个独立的域名——一个用于司机用户,一个用于开发者/企业用户。表面上看,这两个域名各自独立管理账户,但测试表明它们在处理电子邮件变更时存在严重的逻辑漏洞。该漏洞允许攻…...
VLSM基础知识
VLSM(Variable Length Subnet Mask,变长子网掩码)是一种更灵活的子网划分技术,允许在同一网络中使用不同长度的子网掩码,以满足不同子网对主机数量的需求,最大化IP地址利用率。 一、基础概念 传统子网划分…...
小小小病毒(3)(~_~|)
一分耕耘一分收获 声明: 仅供损害电脑,不得用于非法。损坏电脑,作者一律不负责。此作为作者原创,转载请经过同意。 欢迎来到小小小病毒(3) 感谢大家的支持 还是那句话:上代码! …...
WebRTC与EasyRTC:开启智能硬件音视频通讯的全新旅程
在当今数字化时代,音视频通讯技术正以前所未有的速度革新着我们的生活与工作方式。WebRTC与EasyRTC作为这一领域的佼佼者,正携手为智能硬件的音视频通讯注入强大动力,开启全新的篇章。 一、WebRTC与智能硬件融合的崭新趋势 WebRTC技术&…...
Lua 数据库访问
Lua 数据库访问 引言 Lua 是一种轻量级的编程语言,因其简洁性和高效性,常被用于游戏开发、嵌入系统和应用程序开发。在许多情况下,数据库访问是应用程序的核心功能之一。本文将深入探讨在 Lua 中如何进行数据库访问,包括连接数据库、执行查询、处理结果以及异常处理等。 …...
rtsp rtmp 跟 http 区别
SDP 一SDP介绍 1. SDP的核心功能 会话描述:定义会话的名称、创建者、时间范围、连接地址等全局信息。媒体协商:明确媒体流的类型(如音频、视频)、传输协议(如RTP/UDP)、编码格式(如H.264、Op…...
蓝桥杯篇---IAP15F2K61S2串口
文章目录 前言简介串口通信的基本参数1.波特率2.数据位3.停止位4.校验位 串口相关寄存器1.SCON2.SBUF3.PCON4.TMOD5.TH1/TL1 串口使用步骤1.配置波特率2.配置串口模式3.使能串口中断4.发送数据5.接收数据6.处理中断 示例代码:串口发送与接收示例代码:串口…...
Linux 远程文件复制传输-----scp/rsync/sftp
scp(Secure Copy Protocol)是基于 SSH 的安全文件传输工具,可用于在本地和远程计算机之间复制文件或目录。 1. scp(基于 SSH 复制文件) a. 复制文件到远程 从本地复制到远程 scp localfile.txt userremote_host:/remo…...
企业文件安全:零信任架构下的文件访问控制
在企业数字化转型的进程中,传统的文件访问控制模型已难以满足日益复杂的网络安全需求。零信任架构作为一种新兴的安全理念,为企业的文件安全访问提供了全新的解决方案。 一、传统文件访问控制的局限性 传统的文件访问控制主要基于网络边界,…...
用deepseek学大模型05-线性回归
deepseek.com:多元线性回归的目标函数,损失函数,梯度下降 标量和矩阵形式的数学推导,pytorch真实能跑的代码案例以及模型,数据,预测结果的可视化展示, 模型应用场景和优缺点,及如何改进解决及改进方法数据推…...
2009年下半年软件设计师上午真题的知识点整理(附真题及答案解析)
以下是2009年下半年软件设计师上午真题的知识点分类整理,涉及定义的详细解释,供背诵记忆。 1. 计算机组成原理 CPU与存储器的访问。 Cache的作用: 提高CPU访问主存数据的速度,减少访问延迟。存储器的层次结构: 包括寄存器、Cache、主存和辅存…...
Element Plus table 去除行hover效果
需求: 给table的指定行设置高亮背景色且去除掉这些行的hover效果 思路: 给指定行设置css类名选择需要设置高亮的行的单元格,设置鼠标禁用属性让高亮行继承父元素的背景色 考虑到表格的第一列是勾选框,因此仅选择 tr 下除了第一…...
2010年下半年软件设计师考试上午真题的知识点整理(附真题及答案解析)
以下是2010年下半年软件设计师考试上午真题的知识点分类整理,涉及定义的详细解释,供背诵记忆。 1. 计算机组成原理 CPU与存储器的访问。 Cache的作用: 提高CPU访问主存数据的速度,减少访问延迟。存储器的层次结构: 包括寄存器、Cache、主存和…...
Mac Golang 开发环境配置
Mac Golang 开发环境配置 Golang 介绍 Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。 由罗伯特格瑞史莫,罗勃派克(Rob Pike)及肯汤普逊于2007年9月开始设计…...
计算机视觉中图像的基础认知
第一章:计算机视觉中图像的基础认知 第二章:计算机视觉:卷积神经网络(CNN)基本概念(一) 第三章:计算机视觉:卷积神经网络(CNN)基本概念(二) 第四章:搭建一个经典的LeNet5神经网络 一、图像/视频的基本属性…...
理解 WebGPU 中的 navigator.gpu 和 adapter:从浏览器到显卡的旅程
WebGPU 是一种现代图形 API,旨在为 Web 应用程序提供高性能的图形和计算功能。作为 WebGL 的继任者,WebGPU 提供了更底层的硬件访问和更高效的性能。在 WebGPU 开发中,navigator.gpu 是访问 WebGPU API 的入口点,而 adapter 则是浏…...
【ESP32 IDF】ESP32 linux 环境搭建
ESP32 linux 环境搭建 1. 开发环境2. linux指令 1. 开发环境 liunx镜像 liunx镜像地址 : https://mirrors.xjtu.edu.cn/ubuntu-releases/20.04.6/ubuntu-20.04.6-live-server-amd64.iso 有提示你装openssl,务必装上 2. linux指令 工具 sudo apt-get …...
react传递函数与回调函数原理
为什么 React 允许直接传递函数? 回调函数核心逻辑 例子:父组件控制 Modal 的显示与隐藏 // 父组件 (ParentComponent.tsx) import React, { useState } from react; import { Modal, Button } from antd; import ModalContent from ./ModalContent;co…...
目标检测IoU阈值全解析:YOLO/DETR模型中的精度-召回率博弈与工程实践指南
一、技术原理与数学本质 IoU计算公式: IoU \frac{Area\ of\ Overlap}{Area\ of\ Union} \frac{A ∩ B}{A ∪ B}阈值选择悖论: 高阈值(0.6-0.75):减少误检(FP↓)但增加漏检(FN↑…...
使用grafana v11 建立k线(蜡烛图)仪表板
先看实现的结果 沪铜主力合约 2025-02-12 的1分钟k线图 功能介绍: 左上角支持切换主力合约,日期,实现动态加载数据. 项目背景: 我想通过前端展示期货指定品种某1天的1分钟k线,类似tqsdk 的web_gui 生成图形化界面— TianQin Python SDK 3.7.8 文档 项目架构: 后端: fastap…...
Ubuntu下载安装Docker-Desktop
下载 Ubuntu | Docker Docs 预备工作 Ubuntu增加docker apt库-CSDN博客 安装 sudo apt-get updatesudo apt install gnome-terminal# sudo apt install -y docker-composesudo apt-get install ./docker-desktop-amd64.deb 测试 sudo docker run hello-worldHello from D…...
【大模型】DeepSeek 高级提示词技巧使用详解
目录 一、前言 二、DeepSeek 通用提示词技巧 2.1 DeepSeek 通用提示词技巧总结 三、DeepSeek 进阶使用技巧 3.1 DeepSeek一个特定角色的人设 3.1.1 为DeepSeek设置角色操作案例一 3.1.2 为DeepSeek设置角色操作案例二 3.2 DeepSeek开放人设升级 3.2.1 特殊的人设&#…...
23. AI-大语言模型
文章目录 前言一、LLM1. 简介2. 工作原理和结构3. 应用场景4. 最新研究进展5. 比较 二、Transformer架构1. 简介2. 基本原理和结构3. 应用场景4. 最新进展 三、开源1. 开源概念2. 开源模式3. 模型权重 四、再谈DeepSeek 前言 AI 一、LLM LLM(Large Language Mod…...
STM32的启动流程
启动模式 我们知道的复位方式有三种:上电复位,硬件复位和软件复位。当产生复位,并且离开复位状态后, CM33 内核做的第一件事就是读取下列两个 32 位整数的值: (1) 从地址 0x0000 0000 处取出堆…...
C++ Primer 函数匹配
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
Httprint 指纹识别技术:网络安全的关键洞察
引言 Http指纹识别现在已经成为应用程序安全中一个新兴的话题,Http服务器和Http应用程序安全也已经成为网络安全中的重要一部分。从网络管理的立场来看,保持对各种web服务器的监视和追踪使得Http指纹识别变的唾手可得,Http指纹识别可以使得信…...
STM32的HAL库开发---ADC
一、ADC简介 1、ADC,全称:Analog-to-Digital Converter,指模拟/数字转换器 把一些传感器的物理量转换成电压,使用ADC采集电压,然后转换成数字量,经过单片机处理,进行控制和显示。 2、常见的AD…...
PostgreSQL有undo表空间吗?
PostgreSQL有undo表空间吗 PostgreSQL 没有单独的 Undo 表空间,其事务回滚和多版本并发控制(MVCC)机制与 Oracle 等数据库有显著差异。 一 PostgreSQL 的 MVCC 实现 PostgreSQL 通过 多版本并发控制(MVCC) 管理事务…...
Huatuo热更新--安装HybridCLR
1.自行安装unity编辑器 支持2019.4.x、2020.3.x、2021.3.x、2022.3.x 中任一版本。推荐安装2019.4.40、2020.3.26、2021.3.x、2022.3.x版本。 根据你打包的目标平台,安装过程中选择必要模块。如果打包Android或iOS,直接选择相应模块即可。如果你想打包…...
Windows环境安装部署minimind步骤
Windows环境安装部署minimind步骤 必要的软件环境 git git,可下载安装版,本机中下载绿色版,解压到本地目录下(如:c:\soft\git.win64),可将此路径添加到PATH环境变量中,供其他程序…...
前端面试手写--虚拟列表
目录 一.问题背景 二.代码讲解 三.代码改装 四.代码发布 今天我们来学习如何手写一个虚拟列表,本文将把虚拟列表进行拆分并讲解,然后发布到npm网站上. 一.问题背景 为什么需要虚拟列表呢?这是因为在面对大量数据的时候,我们的浏览器会将所有数据都渲染到表格上面,但是渲…...
【算法进阶详解 第一节】树状数组
【算法进阶详解 第一节】树状数组 前言树状数组基础树状数组原理树状数组能够解决的问题 树状数组提高树状数组区间加,区间和操作二维树状数组 树状数组应用树状数组区间数颜色树状数组二维偏序 前言 树状数组在算法竞赛中十分常见,其能解决二维数点&am…...
青少年编程与数学 02-009 Django 5 Web 编程 16课题、权限管理
青少年编程与数学 02-009 Django 5 Web 编程 16课题、权限管理 一、授权授权的主要特点和作用授权的类型应用场景 二、权限系统使用Django内置的权限系统使用组管理权限使用第三方库在视图中应用权限 三、权限管理示例步骤 1: 创建Django项目和应用步骤 2: 定义模型和权限步骤 …...
第四十四篇--Tesla P40+Janus-Pro-7B部署与测试
环境 系统:CentOS-7 CPU: 14C28T 显卡:Tesla P40 24G 驱动: 515 CUDA: 11.7 cuDNN: 8.9.2.26创建环境 conda create --name trans python3.10torch 2.6.0 transformers 4.48.3克隆项目 git clone https:/…...
低成本、高效率且成熟的电商实时数据采集方案:梦想成真?
在电子商务领域,数据是驱动业务决策的核心资源。实时数据采集对于电商企业而言,意味着能够即时洞察市场动态、消费者行为以及运营效果,从而快速调整策略,提升竞争力。然而,如何在保证数据质量的同时,实现低…...
微信小程序之mobx-miniprogram状态管理
目前已经学习了6种小程序页面、组件间的数据通信方案,分别是: 1. 数据绑定: properties 2.获取组件实例: this.selectComponent() 3.事件绑定: this.triggerEvent() 4. 获取应用实例:getApp() 5. 页面间通信: EventChannel 6.事件总线:pubsub-js 在中小型项目…...
uniapp可视化-活动报名表单系统-代码生成器
活动报名表单系统小程序旨在为各类活动组织者提供一个便捷、高效的线上报名管理平台,同时为参与者提供简单易用的报名途径。 主要功能 活动发布:活动组织者可以发布活动的详细信息,包括活动名称、时间、地点、活动内容等。用户可以在小程序中…...
1.从零开始学会Vue--{{基础指令}}
全新专栏带你快速掌握Vue2Vue3 1.插值表达式{{}} 插值表达式是一种Vue的模板语法 我们可以用插值表达式渲染出Vue提供的数据 1.作用:利用表达式进行插值,渲染到页面中 表达式:是可以被求值的代码,JS引擎会将其计算出一个结果 …...
深入解析操作系统控制台:阿里云Alibaba Cloud Linux(Alinux)的运维利器
作为一位个人开发者兼产品经理,我的工作日常紧密围绕着云资源的运维和管理。在这个过程中,操作系统扮演了至关重要的角色,而操作系统控制台则成为了我们进行系统管理的得力助手。本文将详细介绍阿里云的Alibaba Cloud Linux操作系统控制台的功…...
CSS Grid 网格布局,以及 Flexbox 弹性盒布局模型,它们的适用场景是什么?
CSS Grid网格布局和Flexbox弹性盒布局模型都是现代CSS布局的重要工具,它们各自具有独特的优势和适用场景。 作为前端开发工程师,理解这些布局模型的差异和适用场景对于编写高效、可维护的代码至关重要。 CSS Grid网格布局 适用场景: 复杂…...
2025.2.16机器学习笔记:TimeGan文献阅读
2025.2.9周报 一、文献阅读题目信息摘要Abstract创新点网络架构一、嵌入函数二、恢复函数三、序列生成器四、序列判别器损失函数 实验结论后续展望 一、文献阅读 题目信息 题目: Time-series Generative Adversarial Networks会议: Neural Information…...
高通推出骁龙游戏超级分辨率™:充分释放移动游戏性能,带来更持久的续航
Snapdragon Elite Gaming 一直致力于为每位用户打造卓越游戏体验。骁龙支持众多端游级特性,包括144FPS游戏体验、True 10-bit HDR支持的最高视觉质量的超流畅图形,让玩家可以畅享超10亿色的游戏体验。骁龙将许多移动端首创特性引入备受玩家喜爱的游戏中&…...
golangAPI调用deepseek
目录 1.deepseek官方API调用文档1.访问格式2.curl组装 2.go代码1. config 配置2.模型相关3.错误处理4.deepseekAPI接口实现5. 调用使用 3.响应实例 1.deepseek官方API调用文档 1.访问格式 现在我们来解析这个curl 2.curl组装 // 这是请求头要加的参数-H "Content-Type:…...
SOC芯片前端设计对芯片电源完整性的影响
在进行芯片的电源完整性时,因为PI受影响的因素较多,出现问题debug也比较难,所以在进行芯片设计时,需要端到端从前到后进行考虑设计,本篇文章将从芯片前端设计的角度来看看哪些因素会影响到PI的设计。 芯片前端设计的主…...
【区块链】零知识证明基础概念详解
🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 💫个人格言: "如无必要,勿增实体" 文章目录 零知识证明基础概念详解引言1. 零知识证明的定义与特性1.1 基本定义1.2 三个核心…...