C++之unordered_set和unordered_map

C++之unordered_set和unordered_map

一、unordered系列关联式容器 

在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到log_2
N,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好
的查询是,进行很少的比较次数就能够将元素找到,因此在C++11中,STL又提供了4个
unordered系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是
其底层结构不同

1.1 unordered_map 

1.2 unordered_map的文档介绍

1. unordered_map是存储<key, value>键值对的关联式容器,其允许通过keys快速的索引到与
其对应的value。
2. 在unordered_map中,键值通常用于惟一地标识元素,而映射值是一个对象,其内容与此
键关联。键和映射值的类型可能不同。
3. 在内部, unordered_map没有对<kye, value>按照任何特定的顺序排序, 为了能在常数范围内
找到key所对应的value,unordered_map将相同哈希值的键值对放在相同的桶中。
4. unordered_map容器通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭
代方面效率较低。
5. unordered_maps实现了直接访问操作符(operator[]),它允许使用key作为参数直接访问value。
6. 它的迭代器至少是前向迭代器。

1.3unordered_map的使用

unordered_map成员函数

unordered_map的使用

void test_unordered_map1() { unordered_map<string, string> dict; dict.insert(make_pair("insert", "插入")); dict.insert(make_pair("love", "爱")); dict["sort"] = "排序"; dict["miss"]; dict["miss"] = "想念、错过"; unordered_map<string, string>::iterator it = dict.begin(); while (it != dict.end()) { cout << it->first << ":" << it->second << endl; ++it; } cout << endl; } int main() { test_unordered_map1(); return 0; }

注意:
1、[ ]实际调用哈希桶的插入操作,用参数key与V()构造一个默认值往底层哈希桶
中插入,如果key不在哈希桶中,插入成功,返回V(),插入失败,说明key已经在哈希桶中,
将key对应的value返回。
2、unordered_map中key是不能重复的,因此count函数的返回值最大为1


1.4unordered_set的介绍

1、unordered_set是一种容器,它以任意顺序存储唯一的元素,并允许根据元素的值快速检索单个元素。
2、在unordered_set中,元素的值同时也是其键,用于唯一标识该元素。键是不可变的,因此,unordered_set中的元素一旦存入容器就不能被修改——不过可以插入和移除。
3、在内部,unordered_set中的元素并不按任何特定顺序排序,而是根据它们的哈希值被组织到各个桶中,以便通过元素的值直接快速访问单个元素(平均具有常数级的时间复杂度)。
4、unordered_set在通过键访问单个元素方面比有序集合容器更快,不过在对其部分元素进行范围迭代时,通常效率较低。
5、unordered_set的迭代器至少是前向迭代器。


1.5unordered_set的使用

unordered_set成员函数

unordered_set的使用

void test_unordered_set1() { unordered_set<int> us; us.insert(2); us.insert(3); us.insert(2); us.insert(1); us.insert(0); unordered_set<int>::iterator it = us.begin(); while (it != us.end()) { cout << *it << endl; ++it; } cout << endl; } int main() { test_unordered_set1(); return 0; }

注意:unordered_set只能去重,不能左到排序

1.6map、set、unordered_map、unordered_set性能测试

void test_performance() { const size_t N = 1000000; unordered_set<int> us; set<int> s; vector<int> v; v.reserve(N); srand((size_t)time(0)); for (size_t i = 0; i < N; ++i) { v.push_back(rand() + 1); } size_t begin1 = clock(); for (auto e : v) { s.insert(e); } size_t end1 = clock(); cout << "set insert:" << end1 - begin1 << endl; size_t begin2 = clock(); for (auto e : v) { us.insert(e); } size_t end2 = clock(); cout << "unordered_set insert:" << end2 - begin2 << endl; size_t begin3 = clock(); for (auto e : v) { s.find(e); } size_t end3 = clock(); cout << "set find:" << end3 - begin3 << endl; size_t begin4 = clock(); for (auto e : v) { us.find(e); } size_t end4 = clock(); cout << "unordered_set find:" << end4 - begin4 << endl << endl; cout <<"插入数据个数:"<< s.size() << endl; cout <<"插入数据个数:" << us.size() << endl << endl;; size_t begin5 = clock(); for (auto e : v) { s.erase(e); } size_t end5 = clock(); cout << "set erase:" << end5 - begin5 << endl; size_t begin6 = clock(); for (auto e : v) { us.erase(e); } size_t end6 = clock(); cout << "unordered_set erase:" << end6 - begin6 << endl << endl; }

运行结果:

总结:有大量重复数据的时候unordered_set、unordered_map更占优势,但是有序的数据set、map更占优势。

二、unordered_set和unordered_map的OJ题目

在长度2N的数组里找出重复N次的元素

思路:把其放到unordered_map里面去,然后统计次数,算出n的一半,然后找到那个出现次数为一半的元素

class Solution { public: int repeatedNTimes(vector<int>& nums) { unordered_map<int, int> countmap; for (auto element : nums) { countmap[element]++; } int count = nums.size() / 2; for (auto element : countmap) { if (element.second == count) { return element.first; } } //不可能的情况返回-1 return -1; } };

Read more

Python智慧农业信息化服务平台农产品商城系统 小程序

Python智慧农业信息化服务平台农产品商城系统 小程序

文章目录 * 技术架构设计 * 核心功能模块 * 物联网数据整合 * 性能优化策略 * 安全防护措施 * 部署与监控 * 系统设计与实现的思路 * 主要技术与实现手段 * 源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! 技术架构设计 * 前端框架:采用微信小程序原生框架+WXML/WXSS,结合Vant Weapp组件库快速搭建UI界面。 * 后端服务:基于Django REST Framework构建API,支持JWT身份认证与RBAC权限控制。 * 数据库:MySQL存储业务数据,Redis缓存高频访问数据(如商品详情、用户会话)。 * 消息队列:使用RabbitMQ处理异步任务(如订单状态更新、消息推送)。 核心功能模块 * 用户系统:OpenID自动注册/登录,农户与消费者角色分离,个人中心集成实名认证模块。 * 商品管理:支持多级分类、动态SKU、溯源信息(区块链哈希值存储)。 * 订单系统:微信支付接口对接,物流状态实时同步(调用快递鸟API)。 智能推荐:

By Ne0inhk

为什么你的C++ AIGC模型吞吐量卡在100QPS?真相在这3个参数设置

第一章:C++ AIGC模型吞吐量测试概述 在高性能计算与人工智能融合的背景下,C++ 作为底层系统开发的核心语言,广泛应用于 AIGC(AI Generated Content)模型的推理加速与部署优化。吞吐量测试是评估模型在单位时间内处理请求能力的关键指标,直接影响服务的可扩展性与响应效率。通过精确测量每秒处理的请求数(QPS)或样本数,开发者能够识别性能瓶颈,优化内存访问模式、线程调度策略以及计算资源利用率。 测试目标与核心指标 吞吐量测试旨在量化模型在稳定运行状态下的最大处理能力。关键指标包括: * QPS(Queries Per Second):每秒成功响应的请求数量 * 延迟分布:P50、P99 延迟反映系统响应一致性 * CPU/GPU 利用率:评估硬件资源使用效率 * 内存占用:监控驻留集大小与动态分配行为 典型测试流程 1. 构建 C++ 推理服务,集成 ONNX Runtime 或 TensorRT 等引擎 2.

By Ne0inhk
特殊类的设计----《Hello C++ Wrold!》(28)--(C/C++)

特殊类的设计----《Hello C++ Wrold!》(28)--(C/C++)

文章目录 * 前言 * 设计一个不能被拷贝的类 * 设计一个只能在堆上创建对象的类 * 设计一个只能在栈上创建对象的类 * 设计一个不能被继承的类 * 设计一个只能创建一个对象的类(也叫做单例模式) * 单例模式的两种实现方法 * 饿汉模式 * 懒汉模式 前言 在 C++ 面向对象编程体系中,类是封装数据与行为的核心单元,其设计直接关系到程序的安全性、可维护性与性能表现。除了支撑常规业务逻辑的普通类,实际开发中常需面对具有特殊约束的场景:例如防止对象拷贝以规避资源重复释放风险,限定对象创建位置(仅堆或仅栈)以规范内存管理,禁止类被继承以保障核心逻辑不被篡改,或是确保类仅存在一个实例以实现全局资源统一调度 —— 这些需求的实现,正是特殊类设计的核心范畴。 本文聚焦 “特殊类设计” 这一主题,系统拆解五种典型特殊类的实现逻辑与技术细节。从 “不能被拷贝的类” 对拷贝构造函数、赋值运算符的管控,到 “只能在堆 / 栈上创建对象的类” 对构造函数与内存分配接口的限制;从 “不能被继承的类” 基于构造函数私有化(C++98)与final关键字(

By Ne0inhk

为什么要用线程池(C++)?

1)不用线程池时: void handle_request() {     std::thread t([]{         // 干活     });     t.detach(); } 问题很明显: * ❌ 频繁 new thread / destroy thread,开销大 * ❌ 线程数量不可控,可能把系统拖死 * ❌ 不好统一管理、退出、回收 线程池的本质一句话: 线程提前创建好,反复用;任务丢进去,线程自己取。 二、线程池的核心模型(一定要理解) 线程池 ≈ 三样东西 +--------------------+ |   Task Queue       |  <- function<void()> +--------------------+         ▲          | +--------------------+ |   Worker Threads   |  多个 while(true) +--------------------+

By Ne0inhk