当前位置: 首页 > news >正文

C++ 容器——unordered_xxx

       自 C++11 开始,STL 引入了基于 hash table 的 unordered_setunordered_map 等容器,正如其名它们是无序容器。一定数量(据说有测试数据是10000000)元素时无序容器的性能要比对应的有序容器优。

一、容器数据结构

        unordered_set、unordered_map 等容器的 Hash Table(哈希表/散列表)结构通常是:桶(bucket) + 线性表,bucket 一般用 vector 实现,线性表通常采用链表。当插入元素时通过哈希函数计算其哈希值,以哈希值作为 vector 的下标索引,取得元素要插入的链表头,把元素插入进去。也就是说通过 链地址法(Separate Chaining)  解决哈希冲突。

二、哈希函数

        哈希函数是这些容器的核心,也是保证它们高性能的关键。C++11 为基本类型:int、float、double、char、string 提供了哈希函数。 但是要在这些容器中添加自定义类型的元素就必须提供特定的哈希函数

无自定义类的哈希函数

无论是 clang++、还是 g++ 都无法正确如下代码,原因就是:缺失计算 Person 哈希值的函数

#include <string>
#include <unordered_set>class Person {
public:Person(const std::string &name, int age) : _name(name), _age(age) {}private:std::string _name;int         _age;
};int main(int argc, char *argv[]) {std::unordered_set<Person> persons;
}
为自定义类添加哈希函数

查看 unordered_set 的声明、 g++ 的 /usr/include/c++/9/bits/functional_hash.h 可知:

  • unordered_set 的模板参数 Hash 默认设置为 std::hash<Key>,std::hash 是一个类模板;
  • 通过特化 std::hash,支持了诸如 int、double 基本类型的哈希函数;
  • 每个特化版本中重载了函数调用运算符
template<class Key,class Hash = std::hash<Key>,class KeyEqual = std::equal_to<Key>,class Allocator = std::allocator<Key>
> class unordered_set;/// Explicit specialization for int.
_Cxx_hashtable_define_trivial_hash(int)/// Explicit specialization for bool.
_Cxx_hashtable_define_trivial_hash(bool)/// Explicit specialization for char.
_Cxx_hashtable_define_trivial_hash(char)#define _Cxx_hashtable_define_trivial_hash(_Tp) 	\template<>						\struct hash<_Tp> : public __hash_base<size_t, _Tp>  \{                                                   \size_t                                            \operator()(_Tp __val) const noexcept              \{ return static_cast<size_t>(__val); }            \};

综述为 Person 类定义函数对象类实现哈希函数功能

#include <string>
#include <unordered_set>struct Person {Person(const std::string &name, int age) : _name(name), _age(age) {}std::string _name;int         _age;
};struct PersonHash
{size_t operator()(const Person &person) const noexcept{return static_cast<size_t>(person._age + person._name.length());}
};int main(int argc, char *argv[]) {std::unordered_set<Person, PersonHash> persons;persons.insert({"yaoyuan", 30});}
为自定义类添加哈希函数

未完...


文章转载自:

http://7f9Mhkqc.mkydt.cn
http://EtGdncVH.mkydt.cn
http://PCr9PkUJ.mkydt.cn
http://7Nk3260f.mkydt.cn
http://MM1QvXde.mkydt.cn
http://0q3ki0oT.mkydt.cn
http://7UEHPtEj.mkydt.cn
http://Fy0Y7DxW.mkydt.cn
http://2cDb9pXH.mkydt.cn
http://ctRTxqm3.mkydt.cn
http://ttCcvRGZ.mkydt.cn
http://JqGzyC8M.mkydt.cn
http://RMtmq6mL.mkydt.cn
http://suh8XMzq.mkydt.cn
http://QnWBkXIN.mkydt.cn
http://drjVIeuF.mkydt.cn
http://hHyRmomU.mkydt.cn
http://jwHpQ8mw.mkydt.cn
http://HZYDF9Oz.mkydt.cn
http://g9Qg3Igj.mkydt.cn
http://a0Ujedvj.mkydt.cn
http://LMBgBWJ8.mkydt.cn
http://aaYt7g8D.mkydt.cn
http://zwIxCRSD.mkydt.cn
http://chlyZcnp.mkydt.cn
http://e0OzvC8I.mkydt.cn
http://sUJC4gRX.mkydt.cn
http://6TLEdI3Z.mkydt.cn
http://0wlDXXc7.mkydt.cn
http://p1pgGDCj.mkydt.cn
http://www.dtcms.com/a/371375.html

相关文章:

  • 常见设计模式详解
  • 网络爬虫(web crawler)
  • 319章:使用Scrapy框架构建分布式爬虫
  • (LeetCode 面试经典 150 题) 67. 二进制求和(位运算、字符串)
  • 【linux kernel 常用数据结构和设计模式】【数据结构 3】【模拟input子系统input_dev和input_handler之间的多对多关系】
  • 怎么用CXL加速数据库?· SIGMOD‘25
  • Day23_【机器学习—聚类算法—K-Means聚类 及评估指标SSE、SC、CH】
  • Uniapp 怎么修改项目图标和启动页
  • macos安装openjdk17
  • 像素图生成小程序开发全解析:从图片上传到Excel图纸
  • 运维服务方案,运维巡检方案,运维安全保障方案文件
  • 计算机网络相关
  • 【代码讲解】北通手柄遥控 + Mujoco 仿真 SO-ARM100 机械臂末端位姿
  • ARM 体系结构
  • 云平台面试内容(一)
  • React Hooks 钩子
  • js逆向之JSEncrypt的加密
  • Balabolka:免费高效的文字转语音软件
  • 第3天-Jenkins详解-3
  • Linux内核进程管理子系统有什么第四十三回 —— 进程主结构详解(39)
  • Apache 2.0 开源协议详解:自由、责任与商业化的完美平衡-优雅草卓伊凡
  • 【iOS】多界面传值
  • 【C++】简单介绍lambda表达式
  • uv 包管理器:优势解析与使用指南
  • Android studio的adb和终端的adb互相抢占端口
  • 同类软件对比(四):Jupyter vs PyCharm vs VS Code:Python开发工具终极选择指南
  • 【MySQL】数据库的基本操作
  • PaddlePaddle——飞桨深度学习实现手写数字识别任务
  • Docker Compose 运行 Milvus (Mac) 并与 python 连接测试
  • 03-Redis 安装指南:从版本选择到多系统部署(Windows+macOS+Linux)