★ C++进阶篇 ★ map和set
Ciallo~(∠・ω< )⌒☆ ~ 今天,我将继续和大家一起学习C++进阶篇第四章----map和set ~

❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️
澄岚主页:椎名澄嵐-CSDN博客
C++基础篇专栏:★ C++基础篇 ★_椎名澄嵐的博客-CSDN博客
C++进阶篇专栏:★ C++进阶篇 ★_椎名澄嵐的博客-CSDN博客
❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️
目录
一 序列式容器和关联式容器
二 set系列的使用
2.1 set类的介绍
2.2 set的构造和迭代器
2.3 set的增删查
2.4 set的使用
2.5 multiset和set的差异
2.6 两道set经典例题
三 map系列的使用
3.1 map类的介绍
3.2 pair类型介绍
3.3 map的构造
3.4 map的增删查
3.5 构造遍历及增删查使用样例
3.6 insert & operator[ ]
3.7 multimap和map的差异
一 序列式容器和关联式容器
序列式容器:有string、vector、list、deque、array、forward_list等。逻辑结构为线性序列的数据结构,两个位置存储的值之间⼀般没有紧密的关联关系,比如交换⼀下,他依旧是序列式容器。顺序容器中的元素是按他们在容器中的存储位置来顺序保存和访问的。
关联式容器:有map/set系列和unordered_map/unordered_set系列。关联式容器逻辑结构通常是非线性结构, 两个位置有紧密的关联关系,交换⼀下,他的存储结构就被破坏了。顺序容器中的元素是按关键字来保存和访问的。
本次学习的map和set底层是红黑树,红⿊树是⼀颗平衡二叉搜索树。set是key搜索场景的结构, map是key/value搜索场景的结构。
二 set系列的使用
2.1 set类的介绍
set - C++ Reference (cplusplus.com)

- set的声明如上,T就是set底层关键字的类型
- set默认要求T支持小于比较,如果不支持或者想按自己的需求走可以自行实现仿函数传给第二个模版参数
- set底层存储数据的内存是从空间配置器申请的,如果需要可以自己实现内存池,传给第三个参数。
- ⼀般情况下,我们都不需要传后两个模版参数。
- set底层是用红黑树实现,增删查效率是 ,迭代器遍历是走的搜索树的中序,所以是有序的。 O(logN) 。
2.2 set的构造和迭代器
set的各种构造~( 无参默认构造,迭代器区间构造, 拷贝构造,移动构造, initializer列表构造 )

set的支持正向和反向迭代遍历,遍历默认按升序顺序,因为底层是⼆叉搜索树,迭代器遍历走的中序;支持迭代器就意味着支持范围for,set的iterator和const_iterator都不支持迭代器修改数据,修改关键字数据,破坏了底层搜索树的结构。

2.3 set的增删查
set 不支持修改,主要有以下接口~
Member types
key_type -> T
value_type -> T// 单个数据插⼊,如果已经存在则插⼊失败
pair<iterator, bool> insert(const value_type& val);
// 列表插⼊,已经在容器中存在的值不会插⼊
void insert(initializer_list<value_type> il);
// 迭代器区间插⼊,已经在容器中存在的值不会插⼊
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
// 查找val,返回val所在的迭代器,没有找到返回end()
iterator find(const value_type& val);
// 查找val,返回Val的个数
size_type count(const value_type& val) const;
// 删除⼀个迭代器位置的值
iterator erase(const_iterator position);
// 删除val,val不存在返回0,存在返回1
size_type erase(const value_type& val);
// 删除⼀段迭代器区间的值
iterator erase(const_iterator first, const_iterator last);
// 返回⼤于等val位置的迭代器
iterator lower_bound(const value_type& val) const;
// 返回⼤于val位置的迭代器
iterator upper_bound(const value_type& val) const;
2.4 set的使用
- 迭代器 & insert
#include<iostream>
#include<set>
using namespace std;
int main()
{// 去重+升序排序set<int> s1;// 去重+降序排序set<int, greater<int>> s2;s1.insert(5);s1.insert(2);s1.insert(7);s1.insert(5);//set<int>::iterator it = s.begin();auto it = s1.begin();while (it != s1.end()){// error C3892: “it”: 不能给常量赋值// *it = 1;cout << *it << " ";++it;}cout << endl; // 2 5 7// 插入⼀段initializer_list列表值,已经存在的值插入失败s1.insert({ 2,8,3,9 });for (auto e : s1){cout << e << " ";}cout << endl; // 2 3 5 7 8 9set<string> strset = { "sort", "insert", "add" };// 遍历string比较ascll码大小顺序遍历的for (auto& e : strset){cout << e << " ";} cout << endl; // add insert sortreturn 0;
}
-
erase & find
int main()
{set<int> s = { 4,2,7,2,8,5,9 };for (auto e : s){cout << e << " ";}cout << endl;// 删除最小值s.erase(s.begin());for (auto e : s){cout << e << " ";}cout << endl;// 直接删除xint x;cin >> x;int num = s.erase(x);if (num == 0){cout << x << "不存在!" << endl;}for (auto e : s){cout << e << "删除成功!" << " ";}cout << endl;// 直接查找在利⽤迭代器删除xcin >> x;auto pos = s.find(x);if (pos != s.end()){// pos在erase后失效s.erase(pos);}else{cout << x << "不存在!" << endl;}for (auto e : s){cout << e << "删除成功!" << " ";}cout << endl;// 算法库的查找 O(N)auto pos1 = find(s.begin(), s.end(), x);// set⾃⾝实现的查找 O(logN)auto pos2 = s.find(x);// 利⽤count间接实现快速查找cin >> x;if (s.count(x)){cout << x << "在!" << endl;}else{cout << x << "不存在!" << endl;}return 0;
}
注意迭代器失效的问题
int main()
{std::set<int> myset;for (int i = 1; i < 10; i++)myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90for (auto e : myset){cout << e << " ";}cout << endl;// 实现查找到的[itlow,itup)包含[30, 60]区间// 返回 >= 30auto itlow = myset.lower_bound(30);// 返回 > 60auto itup = myset.upper_bound(60);// 实现查找到的[itlow,itup)包含[25, 55]区间// 返回 >= 25auto itlow = myset.lower_bound(25);// 返回 > 55auto itup = myset.upper_bound(55);// 删除这段区间的值myset.erase(itlow, itup);for (auto e : myset){cout << e << " ";}cout << endl;return 0;
}
2.5 multiset和set的差异
multiset和set的使用基本完全类似,主要区别点在于multiset⽀持值冗余,那么 insert/find/count/erase都围绕着⽀持值冗余有所差异,具体参看下面的样例代码理解。
int main()
{// 相比set不同的是,multiset是排序,但是不去重multiset<int> s = { 4,2,7,2,4,8,4,5,4,9 };auto it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;// 相比set不同的是,x可能会存在多个,find查找中序的第⼀个int x;cin >> x;auto pos = s.find(x);while (pos != s.end() && *pos == x){cout << *pos << " ";++pos;}cout << endl;// 相比set不同的是,count会返回x的实际个数cout << s.count(x) << endl;// 相比set不同的是,erase给值时会删除所有的xs.erase(x);for (auto e : s){cout << e << " ";}cout << endl;return 0;
}
2.6 两道set经典例题
1. 两个数组的交集
349. 两个数组的交集 - 力扣(LeetCode)

首先用两个集合s1和s2来存储nums1和nums2的元素,因为集合会自动去重并且排序~
然后,函数用两个迭代器it1和it2来分别遍历s1和s2。在遍历的过程中,如果it1指向的元素小于it2指向的元素,就让it1向后移动一位;如果it1指向的元素大于it2指向的元素,就让it2向后移动一位;如果它们相等,就把这个元素加入到结果向量ret中,并且让it1和it2都向后移动一位~
class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {set<int> s1(nums1.begin(), nums1.end());set<int> s2(nums2.begin(), nums2.end());// 因为set遍历是有序的,有序值,依次⽐较// ⼩的++,相等的就是交集vector<int> ret;auto it1 = s1.begin();auto it2 = s2.begin();while (it1 != s1.end() && it2 != s2.end()){if (*it1 < *it2){it1++;}else if (*it1 > *it2){it2++;}else{ret.push_back(*it1);it1++;it2++;}}return ret;}
};
2. 环形链表
142. 环形链表 II - 力扣(LeetCode)

把每个节点遍历插入set, 若插入时发现set中已经有此节点,则带环。
class Solution {
public:ListNode *detectCycle(ListNode *head) {set<ListNode*> s;ListNode* cur = head;while(cur){if(s.count(cur))return cur;elses.insert(cur);cur = cur->next;}return nullptr;}
};
三 map系列的使用
3.1 map类的介绍

map的声明如上,Key就是map底层关键字的类型,T是map底层value的类型,set默认要求Key⽀持小于比较,如果不⽀持或者需要的话可以自行实现仿函数传给第⼆个模版参数,map底层存储数据的内存是从空间配置器申请的。⼀般情况下,我们都不需要传后两个模版参数。map底层是用红黑树实现,增删查改效率是 O(logN) ,迭代器遍历是⾛的中序,所以是按key有序顺序遍历的。
3.2 pair类型介绍

map 的成员中的 value_type 使用了 pair 类型,那什么是 pair 类型呢~



3.3 map的构造
map的构造我们关注以下⼏个接口即可。 map⽀持正向和反向迭代遍历,遍历默认按key的升序顺序,因为底层是⼆叉搜索树,迭代器遍历⾛的中序;⽀持迭代器就意味着⽀持范围for,map⽀持修改value数据,不⽀持修改key数据,修改关键字数据,破坏了底层搜索树的结构。

3.4 map的增删查
map增接口,插⼊的pair键值对数据,跟set所有不同,但是查和删的接⼝只⽤关键字key跟set是完全类似的,不过find返回iterator,不仅仅可以确认key在不在,还找到key映射的value,同时通过迭代还可以修改value。
Member types
key_type -> The first template parameter (Key)
mapped_type -> The second template parameter (T)
value_type -> pair<const key_type,mapped_type>// 单个数据插⼊,如果已经key存在则插⼊失败,key存在相等value不相等也会插⼊失败
pair<iterator,bool> insert (const value_type& val);
// 列表插⼊,已经在容器中存在的值不会插⼊
void insert (initializer_list<value_type> il);
// 迭代器区间插⼊,已经在容器中存在的值不会插⼊
template <class InputIterator>
void insert (InputIterator first, InputIterator last);// 查找k,返回k所在的迭代器,没有找到返回end()
iterator find (const key_type& k);
// 查找k,返回k的个数
size_type count (const key_type& k) const;// 删除⼀个迭代器位置的值
iterator erase (const_iterator position);
// 删除k,k存在返回0,存在返回1
size_type erase (const key_type& k);
// 删除⼀段迭代器区间的值
iterator erase (const_iterator first, const_iterator last);// 返回⼤于等k位置的迭代器
iterator lower_bound (const key_type& k);
// 返回⼤于k位置的迭代器
const_iterator lower_bound (const key_type& k) const;
3.5 构造遍历及增删查使用样例
int main()
{map<string, string> dict;pair<string, string> kv1("first", "第一个");dict.insert(kv1); // 有名对象dict.insert(pair<string, string>("second", "第二个")); // 匿名对象dict.insert(make_pair("third", "第三个")); // make_pair函数dict.insert({ "forth", "第四个" }); // C++11// 隐式类型转换构造map<string, string> dict2 = { { "left", "左边" }, { "right", "右边" }, { "insert", "插入" }, { "erase", "删除" } };auto it = dict.begin();while (it != dict.end()){// cout << (*it).first << ":" << (*it).second << endl;cout << it->first << ":" << it->second << endl;// 存结构可以用箭头// 实际上是cout << it.operator->()->first << ":" << it.operator->()->second << endl;++it;}return 0;
}
3.6 insert & operator[ ]

insert 插⼊⼀个 pair 对象
- 1 、如果 key 已经在 map 中,插⼊失败,则返回⼀个 pair 对象,返回 pair 对象 first 是 key 所在结点的迭代器, second 是 false。
- 2 、如果 key 不在在 map 中,插⼊成功,则返回⼀个 pair 对象,返回 pair 对象 first 是新插⼊ key 所在结点的迭代器, second 是 true。
- ⽆论插⼊成功还是失败,返回 pair 对象的 first 都会指向 key 所在的迭代器。
- 那么也就意味着 insert 插⼊失败时充当了查找的功能,正是因为这⼀点,insert 可以⽤来实现 operator[]。
- 需要注意的是这⾥有两个 pair ,不要混淆了,⼀个是 map 底层红⿊树节点中存的 pair ,另 ⼀个是 insert 返回值 pair。

![]()
operator[ ] 有插入,查找,修改,三个功能 ~
// operator的内部实现
mapped_type& operator[] (const key_type& k)
{// 1、如果k不在map中,insert会插⼊k和mapped_type默认值,// 同时[]返回结点中存储mapped_type值的引⽤,那么我们可以通过引⽤修改返映射值。所以[]具备了插⼊+修改功能// 2、如果k在map中,insert会插⼊失败,但是insert返回pair对象的first是指向key结点的迭代器,// 返回值同时[]返回结点中存储mapped_type值的引⽤,所以[]具备了查找+修改的功能pair<iterator, bool> ret = insert({ k, mapped_type() });iterator it = ret.first;return it->second;
}
operator[ ]的使用:
确定key存在才能使用[ ]查找~要不就变成插入了~
int main()
{map<string, string> dict;dict.insert(make_pair("sort", "排序"));// key不存在->插入{ "insert", string() }dict["insert"];// 插入+修改dict["left"] = "左边";// 修改dict["left"] = "左边、剩余";// key存在->查找cout << dict["left"] << endl;return 0;
}
使用find统计次数:
int main()
{// 利⽤find和iterator修改功能,统计水果出现的次数string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> countMap;for (const auto& str : arr){// 先查找水果在不在map中// 1、不在,说明⽔果第⼀次出现,则插⼊{⽔果, 1}// 2、在,则查找到的节点中⽔果对应的次数++auto ret = countMap.find(str);if (ret == countMap.end()){countMap.insert({ str, 1 });}else{ret->second++;}}for (const auto& e : countMap){cout << e.first << ":" << e.second << endl;}cout << endl;return 0;
}
使用operator[ ] 统计次数:
int main()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> countMap;for (const auto& str : arr){// []先查找水果在不在map中// 1、不在,说明水果第⼀次出现,则插⼊{水果, 0},同时返回次数的引⽤,++⼀下就变成1次了// 2、在,则返回水果对应的次数++countMap[str]++;}for (const auto& e : countMap){cout << e.first << ":" << e.second << endl;}cout << endl;return 0;
}
3.7 multimap和map的差异
multimap和map的使⽤基本完全类似,主要区别点在于multimap⽀持关键值key冗余,那么 insert/find/count/erase都围绕着⽀持关键值key冗余有所差异,这⾥跟set和multiset完全⼀样,⽐如find时,有多个key,返回中序第⼀个。其次就是multimap不⽀持[ ],因为⽀持key冗余,[ ]就只能⽀持插⼊了,不能⽀持修改。

相关文章:
★ C++进阶篇 ★ map和set
Ciallo~(∠・ω< )⌒☆ ~ 今天,我将继续和大家一起学习C进阶篇第四章----map和set ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页:椎名澄嵐-CSDN博客 C基础篇专栏:★ C基础篇 ★_椎名澄嵐的博客-CSDN博…...
Python知识点:如何使用Nvidia Jetson与Python进行边缘计算
开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! 如何使用Nvidia Jetson与Python进行边缘计算 Nvidia Jetson平台是专为边缘计算设…...
动态分配内存
目录 前言 一.malloc,free函数 1.malloc,free函数原型 2.使用方法 3.具体实例 4.注意事项 二.calloc函数 1.calloc函数原型 2.主要特点 3.使用案例 三.realloc函数 1.realloc函数原型 2.使用案例 3.注意事项 前言 动态内存是指在程序运行时,按需分配和…...
Unity Input System自动生成配置
参考视频 创建及配置新输入系统 New Input System|Unity2022.2 最新教程《勇士传说》入门到进阶|4K_哔哩哔哩_bilibili ProjectSettings设置 Unity编辑器菜单栏选择Edit->Project Settings->Player->Other Settings,将Api Compatibility Level…...
【Windows】在任务管理器中隐藏进程
在此前的一篇,我们已经介绍过了注入Dll 阻止任务管理器结束进程 -- Win 10/11。本篇利用 hook NtQuerySystemInformation 并进行断链的方法实现进程隐身,实测支持 taskmgr.exe 的任意多进程隐身。 任务管理器 代码: // dllmain.cpp : 定义 …...
【TypeScript学习】TypeScript基础学习总结二
主要记录ts中的类、接口与泛型 1.类 无论是在哪种语言中,类都是面向对象编程(OOP)的一个主要实现方式。能够实现代码更加灵活,更具有结构化。类作用都是提供一个模板,通过类可以创建多个具有相同结构的对象。 // 类的定义,与对象…...
中国电信解锁万亿参数大模型:TeleAI的创新与突破
首个由万卡集群训练出来的万亿参数大模型,已被一家央企解锁。 具体而言,为了推动纯国产人工智能的探索,带来这条新路径的正是中国电信人工智能研究院(TeleAI)。 该研究院由中国电信集团的CTO、首席科学家兼院长李学龙…...
戴尔PowerEdge R840服务器亮黄灯 不开机
最近接修到一台东莞用户的DELL PowerEdge R840 服务器因为意外断电后,无法正常开机的问题, 大概故障现象是 插上电源线 按卡机按钮无响应,无法开机,无显示输出,工程师到现场检修,经过idrac中日志分析&#…...
【前端安全】js逆向之微信公众号登录密码
❤️博客主页: iknow181 🔥系列专栏: 网络安全、 Python、JavaSE、JavaWeb、CCNP 🎉欢迎大家点赞👍收藏⭐评论✍ 随着发展,越来越多的登录页面添加了密码加密的措施,使得暴力破解变得不在简单&a…...
C# 泛型使用案例_C# 泛型使用整理
一、系统自带常用的泛型 1.字典,集合 //字典 Dictionary<string, int> dic new Dictionary<string, int>(); //泛型集合 List<int> list new List<int>(); 2.泛型委托,输入参数,输出参数 //泛型 委托---输出参…...
Docker 安装 Citus 单节点集群:全面指南与详细操作
Docker 安装 Citus 单节点集群:全面指南与详细操作 文章目录 Docker 安装 Citus 单节点集群:全面指南与详细操作一 服务器资源二 部署图三 安装部署1 创建网络2 运行脚本1)docker-compose.cituscd1.yml2)docker-compose.cituswk1.…...
Arthas redefine(加载外部的.class文件,redefine到JVM里 )
文章目录 二、命令列表2.2 class/classloader相关命令2.2.3 redefine(加载外部的.class文件,redefine到JVM里 )举例1:加载新的代码,jad/mc 命令使用举例2:上传 .class 文件到服务器的技巧 本人其他相关文章…...
C++教程(三):c++常用的配置文件类型
目录 1. INI 文件 2. JSON 文件 3. YAML 文件 4. XML 文件 5. TOML 文件 6. 二进制配置文件(Protocol Buffers, MessagePack, Avro 等) 总结 在 C 项目中,常用的配置文件类型有多种选择,具体选择取决于项目的复杂性、可读性…...
Arduino Uno控制雨滴传感器模块的设计方案
以下是Arduino Uno控制雨滴传感器模块的设计方案: 一、硬件准备: 1. Arduino Uno 开发板一块。 2. 雨滴传感器模块一个。 3. 杜邦线若干。 4. 9V直流电源一个。 二、硬件连接: 1. 将Arduino Uno板的Vin引脚、GND引脚分别连接到9V直流电…...
华为常见命令手册
常见命令 display ip interface brief —> 查看设备上的每个接口的IP地址【地址/掩码/状态】 display interface gi0/0/0 → 查看该接口的MAC 地址 ipconfig → 查看 PC 上面的 IP地址 display arp → 查看设备的 ARP 表 arp -a → 查看 PC 上面的 ARP 表 display m…...
TinyAP:使用TinyML对抗Wi-Fi攻击的智能接入点
论文标题: 英文:TinyAP: An intelligent Access Point to combat Wi-Fi attacks using TinyML中文:TinyAP:使用TinyML对抗Wi-Fi攻击的智能接入点 作者信息: Anand Agrawal 和 Rajib Ranjan Maiti,来自印…...
grafana频繁DataSourceError问题
背景 随着 Grafana 数据量的不断增加,逐渐暴露出以下问题: Grafana 页面加载缓慢;Grafana 告警频繁出现 DatasourceError 错误。 对于第一个问题,大家可以参考这篇文章:Grafana 加载缓慢的解决方案。 不过…...
python-ds:Python 中的数据结构库(适用于面试的数据结构和算法合集)
在软件开发中,数据结构是组织和存储数据的方式,对算法的效率和程序的性能至关重要。Python 提供了许多内置的数据结构,但在一些复杂的应用场景中,原生数据结构可能无法满足特定需求。这时,一个功能强大、易于使用的数据…...
AccessoriesqueryController
目录 1、 AccessoriesqueryController 1.1、 库存配件查询 1.2、 查询仓库 1.2.1、 //把数据库数据加到表格:跟默认然一行数据进行合并 1.3、 /// 查询 1.3.1、 配件编码查询 1.3.2、 配件名称查询 1.3.3、 配件类型查询 AccessoriesqueryControlle…...
M3u8视频由手机拷贝到电脑之后,通过potplayer播放报错找不到文件地址怎么解决?
该文章前面三节主要介绍M3u8视频是什么,视频播放错误(找不到地址)的解决方法在后面 M3U8是一种多媒体播放列表文件格式,主要用于流媒体播放。 一、文件格式特点 1. 文本文件:M3U8是一个采用 UTF-8 编码的文本文件,这意味着它可…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...
云原生安全实战:API网关Envoy的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口,负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...
