【C++进阶篇】C++容器完全指南:掌握set和map的使用,提升编码效率

C++容器的实践与应用:轻松掌握set、map与multimap的区别与用法

  • 一. 序列式容器与关联式容器
    • 1.1 序列式容器 (Sequential Containers)
    • 1.2 关联式容器 (Associative Containers)
  • 二. set系列使用
    • 2.1 set的构造和迭代器
    • 2.2 set的增删查
      • 2.2.1 插入
      • 2.2.2 查找
      • 2.2.3 删除
    • 2.3 multiset和set的差异
  • 三. map系列使用
    • 3.1 pair类
      • 3.1.1 定义与创建
      • 3.1.2 访问元素
    • 3.2 map构造
    • 3.3 map增删查
      • 3.3.1 插入
      • 2.2.2 查找
      • 2.2.3 删除
    • 3.4 map[]功能(重点)
      • 3.4.1 基本功能
      • 3.4.2 返回值类型
      • 3.4.3 自动插入特性
    • 3.5 multimap和map的差异
  • 四. 最后

在C++中,容器是存储和操作数据的核心工具。序列式容器(如vector、list)通过线性顺序存储数据,而关联式容器(如set、map)则通过键值对存储数据,允许更高效的查找、插入和删除。set是一个存储唯一元素的容器,内部自动排序,底层通常使用红黑树实现。它支持高效的查找和元素去重。map是存储键值对的容器,每个键都是唯一的,值可以重复,同样基于红黑树实现,提供快速的键值对查找。在需要快速检索、插入或删除元素时,set和map是非常实用的选择。

一. 序列式容器与关联式容器

1.1 序列式容器 (Sequential Containers)

序列式容器按照元素的插入顺序进行存储,它们提供了对元素的线性访问。序列式容器的元素是有顺序的,可以通过下标或迭代器来访问。常见的序列式容器包括:

  • vector:动态数组,支持快速的随机访问。适用于频繁访问元素,但在中间插入或删除元素时性能较差。

  • deque:双端队列,支持在两端快速插入和删除元素,但相比 vector,在访问和修改元素时稍慢。

  • list:双向链表,支持在任意位置快速插入和删除元素,但不支持随机访问。

  • array:固定大小的数组,支持快速随机访问,但在大小固定时使用。

  • forward_list:单向链表,比 list 更节省内存,但只支持向前遍历。

1.2 关联式容器 (Associative Containers)

关联式容器是基于键值对的容器,每个元素由键和值组成,并且通过键进行访问。它们通常提供基于键的排序和查找功能,能够高效地查找、插入和删除元素。常见的关联式容器包括:

  • set:存储唯一元素的集合,自动排序。可以高效地判断元素是否存在。

  • map:存储键值对,其中每个键都是唯一的,值可以重复。自动按照键排序。

  • multiset:与 set 类似,但允许存储重复的元素。

  • multimap:与 map 类似,但允许存储重复的键。

声明:本篇文章重点介绍关联式容器中的set,map

二. set系列使用

set的底层是用红黑树实现的,增删查效率是 O(logN),迭代器的遍历是中序,所以是有序的。

2.1 set的构造和迭代器

set的迭代器是双向迭代器,遍历默认是升序的,因为底层说到底还是二叉搜索树,所以迭代器(const和非const版本迭代器)都不支持修改数据,会破坏二叉搜索树的结构。

构造类型原型功能
无参默认构造explicit set (const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());构造一个指定类型T的对象
迭代器区间构造template set(InputIterator first, InputIterator last,const key_compare & comp = key_compare(),const allocator_type & = allocator_type());使用迭代器区间初始化对象
初始化列表构造set(initializer_list<value_type> il,const key_compare & comp = key_compare(),const allocator_type & alloc = allocator_type());使用初始化列表构造对象
拷贝构造set (const set& x);使用拷贝构造对象
迭代器原型功能
正向迭代器iterator begin();iterator end()正向遍历容器中的数据
反向迭代器reverse_iterator rbegin();reverse_iterator rend();反向遍历容器中的数据

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#include<iostream>
#include<set>
using namespace std;int main()
{//无参默认构造set<int> s1;cout << "修改前s1: ";for (auto ch : s1){cout <<"原:s1 " << ch;}cout << endl;//迭代器区间构造set<int> s2({ 1,2,3,4,5,6,7,8,9,10 });//initializer 列表构造//set<int> s1(s2.begin(), s2.end());错误写法,s1重定义//使用赋值,或者直接插入//s1.insert(s2.begin(),s2.end())s1 = set<int>(s2.begin(), s2.end());//创建临时对象,进行赋值cout << "修改后s1:";for (auto ch : s1){cout << ch << " ";}cout << endl;//拷贝构造set<int> s3(s1);cout << "s3: ";for (auto ch : s3){cout <<ch << " ";}cout << endl;// 正确的反向遍历cout << "Reverse traversal of s3: ";for (auto rit = s3.rbegin(); rit != s3.rend(); ++rit) {cout << *rit << " ";}cout << endl;return 0;
}

2.2 set的增删查

2.2.1 插入

类型原型功能
单个插入pair<iterator,bool> insert (const value_type& val);插入单个数据,插入已经存在插入失败
列表插入insert (initializer_list<value_type> il);使用初始化列表插入元素
迭代器区间插入template void insert(InputIterator first, InputIterator last);使用迭代器区间插入元素

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#include<iostream>
#include<set>
using namespace std;int main()
{int a = 10;set<int> s;s.insert(a);//插入单个数据for (auto ch : s){cout << ch;}cout << endl;s.insert({ 1,2,3,4,5,6,7,8,9 });//初始化列表插入for (auto ch : s){cout << ch<<" ";}cout << endl;set<int> s3({ 10,20,30,40,50,60,70,80,90,100 });s.insert(s3.begin(), s3.end());//迭代器区间插入数据for (auto ch : s){cout << ch << " ";}cout << endl;return 0;
}

2.2.2 查找

类型原型功能
查找单个元素iterator find (const value_type& val);查找val,返回val所在的迭代器,没有找到返回end()
查找每个元素的总出现个数size_type count (const value_type& val) const;查找val,返回Val的个数

下面将给出一个整合代码演示上述的功能:

  • 示例代码:

#include<iostream>
#include<set>
using namespace std;int main()
{set<int> s;s.insert({ 1,2,3,4,5,6,7,8,9 });//初始化列表插入for (auto ch : s){cout << ch<<" ";}cout << endl;auto it = s.find(6);//存在返回所在迭代器cout << *it << endl;it = s.find(10);//不存在不可进行解引用//cout << *it << endl;error程序会终止int ret = s.count(6);cout << ret << endl;//查找6出现的总个数return 0;
}

2.2.3 删除

类型原型功能
删除单个元素size_type erase (const value_type& val);删除val,val不存在返回0,存在返回1
删除迭代器位置iterator erase (const_iterator position);删除⼀个迭代器位置的值
删除迭代器区间iterator erase (const_iterator first, const_iterator last)删除⼀段迭代器区间的值

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>
#include<set>
using namespace std;int main()
{set<int> s;s.insert({ 1,2,3,4,5,6,7,8,9 });//初始化列表插入cout << "删除前: ";for (auto ch : s){cout << ch<<" ";}cout << endl;cout << "删除5后: ";s.erase(5);//删除单个值for (auto ch : s){cout << ch << " ";}cout << endl;cout << "删除8后: ";auto it = s.find(8);s.erase(it);//删除迭代器位置的值for (auto ch : s){cout << ch << " ";}cout << endl;cout << "全部删除后: ";s.erase(s.begin(), s.end());//删除迭代器区间区间的值,等效于s.clear()for (auto ch : s){cout << ch << " ";}cout << endl;return 0;
}

补充:

// 返回⼤于等val位置的迭代器

  • iterator lower_bound (const value_type& val) const;

// 返回⼤于val位置的迭代器

  • iterator upper_bound (const value_type& val) const;

2.3 multiset和set的差异

multiset和set的使⽤基本完全类似,主要区别点在于multiset⽀持值冗余,说白就是允许插入相同的值。
下面主要来看insert/find/count/erase都围绕着⽀持值冗余有所差异,示例代码:


```cpp
#include<iostream>
#include<set>
using namespace std;
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;
}

三. map系列使用

map的底层是红黑树,key/value结构场景,也是有序的。

3.1 pair类

在C++中,pair 是标准模板库(STL)提供的一个模板类,用于将两个可能不同类型的对象组合成一个单一单元。

3.1.1 定义与创建

#include // 包含pair的头文件
// 创建pair的几种方式
std::pair<int, double> p1; // 默认构造,两个元素被值初始化
std::pair<int, double> p2(1, 3.14); // 直接初始化 std::pair<int,
double> p3 = {2, 2.718}; // 列表初始化(C++11起) auto p4 =
std::make_pair(3, 1.618); // 使用make_pair辅助函数

3.1.2 访问元素

int first_element = p2.first; // 访问第一个元素(int类型)
double second_element = p2.second; // 访问第二个元素(double类型)

结论:pair 是C++中处理简单二元组合的高效工具,在需要临时组合两个相关值时非常有用。对于更复杂的数据结构,建议使用 struct 或 class 来提高代码可读性。

3.2 map构造

map的迭代器是双向迭代器,遍历默认是升序的,因为底层说到底还是二叉搜索树,所以迭代器(const和非const版本迭代器)都不支持修改数据,会破坏二叉搜索树的结构。

构造类型原型功能
无参默认构造explicit map(const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());构造一个指定类型T的对象
迭代器区间构造template map(InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type & = allocator_type());使用迭代器区间初始化对象
初始化列表构造map(initializer_list<value_type> il,const key_compare & comp = key_compare(),const allocator_type & alloc = allocator_type());使用初始化列表构造对象
拷贝构造map (const map& x);使用拷贝构造对象
迭代器原型功能
正向迭代器iterator begin();iterator end();正向遍历容器中的数据
反向迭代器reverse_iterator rbegin();reverse_iterator rend();反向遍历容器中的数据

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#include<iostream>
#include<map>
using namespace std;int main()
{//无参默认构造map<string, string> t1;for (auto entry : t1){cout << entry.first << " -> " << entry.second << endl;}cout << endl;//初始化列表构造map<string, string> t2({{ "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;//迭代器区间构造map<string, string> t3(t2.begin(), t2.end());for (auto entry : t3){cout << entry.first << " -> " << entry.second << endl;}cout << endl;//拷贝构造map<string, string> t4(t2);for (auto entry : t4){cout << entry.first << " -> " << entry.second << endl;}cout << endl;//正向迭代器遍历auto it = t4.begin();while (it != t4.end()){cout << it->first << " " << it->second << endl;++it;}cout << endl;//反向迭代器遍历for (auto it = t4.rbegin(); it != t4.rend(); it++){cout << it->first << " " << it->second << endl;}return 0;
}

3.3 map增删查

3.3.1 插入

类型原型功能
单个插入pair<iterator,bool> insert (const value_type& val);单个数据插⼊,如果已经key存在则插⼊失败,key存在相等value不相等也会插⼊失败
列表插入void insert (initializer_list<value_type> il);列表插⼊,已经在容器中存在的值不会插⼊
迭代器区间插入template void insert(InputIterator first, InputIterator last);使用迭代器区间插入元素

下面将给出一个整合代码演示上述的功能:

  • 示例代码:

#include<iostream>
#include<map>
using namespace std;int main()
{pair<string, string> s("insert", "插入");map<string, string> t1;t1.insert(s);//插入单个元素cout << "t1: ";for (auto entry : t1){cout << entry.first << " -> " << entry.second << endl;}cout << endl;map<string, string> t2;t2.insert({ { "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });//初始化列表插入cout << "t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;map<string, string> t3;t3.insert(t2.begin(), t2.end());//迭代器区间插入cout << "t3: ";for (auto entry : t3){cout << entry.first << " -> " << entry.second << endl;}cout << endl;return 0;
}

2.2.2 查找

类型原型功能
查找单个元素iterator find (const value_type& val);查找val,返回val所在的迭代器,没有找到返回end()
查找每个元素的总出现个数size_type count (const value_type& val) const;查找val,返回Val的个数

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#include<iostream>
#include<map>
using namespace std;int main()
{map<string, string> t2;t2.insert({ { "apple", "苹果" },{ "apple", "苹果" },{ "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });//初始化列表插入cout << "t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}auto it = t2.find("apple");//返回apple位置所在的迭代器cout << it->first << " " << it->second << endl;int ret = t2.count("apple");//查找apple出现的总次数cout << ret << endl;return 0;
}

2.2.3 删除

类型原型功能
删除单个元素size_type erase (const value_type& val);删除val,val不存在返回0,存在返回1
删除迭代器位置iterator erase (const_iterator position);删除⼀个迭代器位置的值
删除迭代器区间iterator erase (const_iterator first, const_iterator last)删除⼀段迭代器区间的值

示例代码:


#include<iostream>
#include<map>
using namespace std;int main()
{map<string, string> t2;t2.insert({ { "apple", "苹果" },{ "apple", "苹果" },{ "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });//初始化列表插入cout << "删除前t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;t2.erase("apple");//删除指定元素值cout << "前t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;auto it = t2.find("orange");t2.erase(it);//删除迭代器位置的值cout << "中t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;t2.erase(t2.begin(), t2.end());//删除迭代器区间的值cout << "后t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}return 0;
}

3.4 map[]功能(重点)

3.4.1 基本功能

  1. 访问元素:如果键存在于map中,operator[]会返回该键对应的值的引用。
  2. 修改元素:通过返回的引用,可以直接修改该键对应的值。
  3. 插入元素:如果键不存在于map中,operator[]会插入一个新的键值对,其中键是给定的键,值是值类型的默认构造值(对于内置类型如int、string等,默认构造值通常是0或空字符串;对于自定义类型,则是其默认构造函数创建的对象)。

3.4.2 返回值类型

operator[]返回的是值的引用(value_type&),这允许对值进行直接修改。

3.4.3 自动插入特性

当使用operator[]访问一个不存在的键时,map会自动插入一个新的键值对。
新插入的键的值部分是其值类型的默认构造值。

  • 使用实例:
#include<iostream>
#include<map>
#include<string>
using namespace std;int main() {map<string, int> wordCount;// 访问并修改现有元素wordCount["apple"] = 10; // 插入或修改键为"apple"的元素cout << "apple: " << wordCount["apple"] << endl; // 输出: apple: 10// 访问不存在的键,自动插入新元素cout << "banana: " << wordCount["banana"] << endl; // 输出: banana: 0(因为int的默认构造值是0)// 修改自动插入的元素wordCount["banana"] += 5;cout << "banana: " << wordCount["banana"] << endl; // 输出: banana: 5// 使用at()方法访问元素(需要确保键存在)try {cout << "orange: " << wordCount.at("orange") << endl;} catch (const out_of_range& e) {cout << "orange: " << e.what() << endl; // 输出: orange: map::at: key not found}return 0;
}

3.5 multimap和map的差异

multimap和map的使⽤基本完全类似,主要区别点在于multimap⽀持关键值key冗余,那么
insert/find/count/erase都围绕着⽀持关键值key冗余有所差异,

  • 示例代码:
#include <iostream>
#include <map>
#include <string>using namespace std;int main() {// 创建multimap并插入数据multimap<string, int> scores = {{"Alice", 90},{"Bob", 85},{"Alice", 95},  // 允许重复的key{"Charlie", 88}};// 1. 查找操作(返回第一个匹配项)auto it = scores.find("Alice");if (it != scores.end()) {cout << "找到Alice的第一个分数: " << it->second << endl; // 输出90}// 2. 计数操作(统计重复key的数量)int count = scores.count("Alice");cout << "Alice出现的次数: " << count << endl; // 输出2// 3. 范围查找(获取所有匹配项)cout << "所有Alice的分数: ";auto range = scores.equal_range("Alice");for (auto itr = range.first; itr != range.second; ++itr) {cout << itr->second << " "; // 输出90 95}cout << endl;// 4. 删除操作(删除所有匹配项)scores.erase("Alice");cout << "删除Alice后剩余元素数量: " << scores.size() << endl; // 输出2(Bob和Charlie)// 5. 尝试使用[]操作符(会编译失败)// scores["David"] = 78; // 错误:multimap不支持[]操作符return 0;
}

通过这个示例可以看出,multimap在处理需要多个相同key的场景时比map更灵活,但相应地也失去了一些特性(如[]操作符的直接访问能力)。在实际开发中,应根据是否需要key唯一性来选择合适的数据结构。

四. 最后

本文详述了C++中关联式容器set、multiset、map、multimap的用法,涵盖构造、迭代器、增删查等操作。set自动排序去重,multiset允许重复;map存储键值对,multimap支持键冗余。重点解析了map的[]操作符自动插入特性及multimap的范围查找。通过代码示例展示了各容器的核心功能与应用场景,是学习C++标准库关联容器的实用指南。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/81428.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2_Spring【IOC容器中获取组件Bean】

Spring中IOC容器中获取组件Bean 实体类 //接口 public interface TestDemo {public void doSomething(); } // 实现类 public class HappyComponent implements TestDemo {public void doSomething() {System.out.println("HappyComponent is doing something...")…

安卓开饭-ScrollView内嵌套了多个RecyclerView,只想与其中一个RecyclerView有联动

在 Android 开发中&#xff0c;将 RecyclerView 嵌套在 ScrollView 内通常会导致性能问题和滚动冲突&#xff0c;应尽量避免这种设计。以下是原因和替代方案&#xff1a; 为什么不推荐 RecyclerView ScrollView&#xff1f;​​ 性能损耗​ RecyclerView 本身已自带高效回收复…

HTTP 请求中 Content-Type 头部

HTTP 请求中 Content-Type 头部可以设置的各种不同的传输格式。multipart/form-data 只是其中一种,主要用于传输包含文件的数据。 以下是一些常见的 HTTP 请求体的 Content-Type 及其用途: 常见的数据传输格式 (Content-Type) 列表: application/json: 描述: 用于传输 JSO…

【U-boot 命令使用】

文章目录 1 查询有哪些命令2 信息查询命令dbinfo - 查看板子信息printenv- 输出环境变量信息version - 输出uboot版本信息 3 环境变量操作命令修改环境变量新建环境变量删除环境变量 4 内存操作命令md命令nm命令mm命令mv命令cp命令cmp命令 5 网络操作命令与网络有关的环境变量p…

初学者如何用 Python 写第一个爬虫?

初学者如何用 Python 写第一个爬虫&#xff1f; 一、爬虫的基本概念 &#xff08;一&#xff09;爬虫的定义 爬虫&#xff0c;英文名为 Web Crawler&#xff0c;也被叫做网络蜘蛛、网络机器人。想象一下&#xff0c;有一个勤劳的小蜘蛛&#xff0c;在互联网这个巨大的蜘蛛网中…

IDE/IoT/搭建物联网(LiteOS)集成开发环境,基于 VSCode + IoT Link 插件

文章目录 概述IDE安装安装旧版本VSCode安装插件安装问题和解决手动安装SDK包手动下载依赖工具 IoTLink配置IoTLink Home用户设置-工具链-编译器用户设置-工具链-构建器用户设置-工具链-烧录器用户设置-SDK管理工程设置-SDK配置工程设置-编译器工程设置-调试器 创建工程Demo 源码…

深度剖析:Dify+Sanic+Vue+ECharts 搭建 Text2SQL 项目 sanic-web 的 Debug 实战

目录 项目背景介绍sanic-web Dify\_service handle\_think\_tag报错NoneType问题描述debug Dify调用不成功&#xff0c;一直转圈圈问题描述debug 前端markdown格式只显示前5页问题描述debug1. 修改代码2.重新构建1.1.3镜像3.更新sanic-web/docker/docker-compose.yaml4. 重新部…

理想AI Talk第二季-重点信息总结

一、TL&#xff1b;DR 理想为什么要做自己的基模&#xff1a;座舱家庭等特殊VLM场景&#xff0c;deepseek/openai没有解决理想的基模参数量&#xff1a;服务端-300B&#xff0c;VLencoder-32B/3.6B&#xff0c;日常工作使用-300B&#xff0c;VLA-4B为什么自动驾驶可以达成&…

TensorRT

TensorRT 下载 TensorRT 7.1.3.4 TAR压缩包&#xff0c;解压到安装目录&#xff1a; tar xzvf TensorRT-7.1.3.4.Ubuntu-16.04.x86_64-gnu.cuda-11.0.cudnn8.0.tar.gz 添加 TensorRT lib 到环境变量&#xff1a; gedit ~/.bashrc # 添加 export LD_LIBRARY_PATH$LD_LIBRARY_PAT…

【NGINX】 -9 nginx + tomcat实现的多级反向代理

文章目录 1、tomcat的安装 (centos版本)1.1 安装Java依赖环境1.2 安装tomcat 2、tomcat的虚拟主机的配置2.1 配置多级目录 3、利用nginx的反向代理实现将转发指向一个虚拟机3.1 nginx服务器的配置3.2 客户端配置 4、 反向多级代理代理服务器操作nginx 1 服务器nginx 2 服务器to…

基于requests_html的python爬虫

前言&#xff1a;今天介绍一个相对性能更高的爬虫库requests_html&#xff0c;会不会感觉和requests有点联系&#xff1f;是的。为什么开始不直接介绍呢&#xff1f;因为我觉得requests是最基本入门的东西&#xff0c;并且在学习过程中也能学到很多东西。我的python老师在介绍这…

【架构篇】架构类型解释

架构设计的本质&#xff1a;从模糊概念到系统化思维 摘要 “架构”是系统设计的灵魂&#xff0c;但许多人对它的理解仍停留在抽象层面。本文系统解析架构的8大核心维度&#xff0c;结合设计原则、案例与误区分析&#xff0c;帮助开发者建立从战略到落地的完整认知框架。 一、架…

用Python绘制梦幻星空

用Python绘制梦幻星空 在这篇教程中&#xff0c;我们将学习如何使用Python创建一个美丽的星空场景。我们将使用Python的图形库Pygame和随机库来创建闪烁的星星、流星和月亮&#xff0c;打造一个动态的夜空效果。 项目概述 我们将实现以下功能&#xff1a; 创建深蓝色的夜…

PyTorch循环神经网络(Pytotch)

文章目录 循环神经网络&#xff08;RNN&#xff09;简单的循环神经网络长短期记忆网络&#xff08;LSTM&#xff09;门控循环单元&#xff08;GRU&#xff09; 循环神经网络&#xff08;RNN&#xff09; 循环神经网络&#xff08;RecurrentNeuralNetwork&#xff0c;RNN&#…

用算术右移实现逻辑右移及用逻辑右移实现算术右移

函数srl()用算术右移实现逻辑右移&#xff0c;函数sra()用逻辑右移实现算术右移。 程序代码 int sra(int x,int k); unsigned int srl(unsigned int x, int k);void main() {int rx1,k,x1;unsigned int rx2,x2;k3;x10x8777;x20x8777;rx1sra(x1, k);rx2srl(x2, k);while(1); }…

pojo层、dao层、service层、controller层的作用

在Java Web开发中&#xff0c;常见的分层架构&#xff08;如Spring Boot项目&#xff09;通常包含POJO层、DAO层、Service层和Controller层&#xff0c;各层职责明确&#xff0c;协同工作。以下是各层的作用及相互关系&#xff1a; 1. POJO层&#xff08;Model/Entity层&#…

【Linux网络】五种IO模型与阻塞IO

IO 在Linux网络环境里&#xff0c;IO&#xff08;Input/Output&#xff09;指的是网络数据在系统与外部网络&#xff08;像其他设备、服务器或者客户端&#xff09;之间进行传输的过程。 它是网络编程和系统性能优化的核心内容。 IO &#xff1a;INPUT和OUTPUT&#xff08;站…

入门OpenTelemetry——应用自动埋点

埋点 什么是埋点 埋点&#xff0c;本质就是在你的应用程序里&#xff0c;在重要位置插入采集代码&#xff0c;比如&#xff1a; 收集请求开始和结束的时间收集数据库查询时间收集函数调用链路信息收集异常信息 这些埋点数据&#xff08;Trace、Metrics、Logs&#xff09;被…

大数据场景下数据导出的架构演进与EasyExcel实战方案

一、引言&#xff1a;数据导出的演进驱动力 在数字化时代&#xff0c;数据导出功能已成为企业数据服务的基础能力。随着数据规模从GB级向TB级甚至PB级发展&#xff0c;传统导出方案面临三大核心挑战&#xff1a; ‌数据规模爆炸‌&#xff1a;单次导出数据量从万级到亿级的增长…

拓展运算符与数组解构赋值的区别

拓展运算符与数组解构赋值是ES6中用于处理数组的两种不同的特性&#xff0c;它们有以下区别&#xff1a; 概念与作用 • 拓展运算符&#xff1a;主要用于将数组展开成一系列独立的元素&#xff0c;或者将多个数组合并为一个数组&#xff0c;以及在函数调用时将数组作为可变参…