【C++STL详解(十三)】unordered系列容器的介绍与使用

2024-08-30 18:44

本文主要是介绍【C++STL详解(十三)】unordered系列容器的介绍与使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

前言

一、unordered_map

介绍

使用 

构造方式

修改 

容量

迭代器

元素访问

查询

桶操作 

二、unordered_set

介绍

使用

构造

修改

容量

 迭代器(只有单向)

查询

桶操作 

三、unordered系列的性能测试


前言

前面提到的map/set是C++98提供的关联式容器,底层结构是红黑树,最差情况下需要比较树得高度次,若树的结点十分多时,查询效率也不是很理想。C++11中,又提供了4个unordered系列容器,使用起来和map/set基本类似,只是底层结构不同。unordered系列底层是哈希结构(严格来说是哈希桶结构),最快的查询可以达到O(1)。

一、unordered_map

介绍

  • unordered_map是存储<key,value>键值对的关联式容器,KV模型
  • 键值key通常用于惟一地标识元素(不存在相同元素),而映射值是一个对象,其内容与此
    键关联。键和映射值的类型可能不同。
  • 内部没有任何的排序,是无序的,这点和map的最大区别,map有序
  • unordered_map通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭
    代方面效率较低。
  • 同样也支持operator【】访问
  • 底层是哈希桶结构
  • 迭代器是单向的,因为底层结构

使用 

使用上和map可以说是基本类似了!除了迭代器

构造方式

	unordered_map<string, int> m;//无参构造unordered_map<string, int> m1(m);//拷贝构造unordered_map<string, int> m2(m1.begin(), m1.end());//迭代器区间构造//初始化列表构造unordered_map<string, int> m3 ={ { "aa", 2 }, { "bb",3 } };

修改 

insert向容器中插入键值对
erase删除键值对
clear清空元素
swap交换两个容器内容
	unordered_map<int, int> m;//无参构造vector<int> a = {3,6,9,4,2,10};for (auto b : a){m.insert({ b,b });}m.erase(3);unordered_map<int, int> m1;m.swap(m1);m.clear();

容量

	unordered_map<string, int> m3 ={ { "aa", 2 }, { "bb",3 } };m3.empty();//判空m3.size();//大小

迭代器

begin()返回第一个元素的迭代器
end()返回最后一个元素的下一个位置的迭代器
cbegin()返回第一个元素的const迭代器
cend()返回最后一个元素的下一个位置的const迭代器
	unordered_map<string, int> m3 ={ { "aa", 2 }, { "bb",3 } };auto it = m3.begin();while (it!=m3.end()){cout << it->first << ":" << it->second << endl;++it;}

 注意:这个系列只提供单向迭代器!!

元素访问

operator【】:返回key对应的value的引用,和map一样!功能强大,既能插入又能修改!

	unordered_map<string, int> m3 ={ { "aa", 2 }, { "bb",3 } };m3["aa"] = 4;

查询

iterator find ( const key_type& k )放回key在哈希桶的位置
size_type count ( const key_type& k ) const;返回哈希桶中关键码为key的个数

注意:Key是唯一的,不允许重复,所以count为0/1!

	auto it = m3.find("aa");m3.count("aa");

桶操作 

bucket_count()返回桶的个数
bucket_size(n)返回n号桶中有效元素的总个数
bucket(key)返回元素key所在的桶号

二、unordered_set

介绍

  • unordered_set是存储key的关联式容器,K模型,底层可以看出<key,key>
  • 键值key通常用于惟一地标识元素(不存在相同元素)
  • 内部没有任何的排序,是无序的,这点和set的最大区别,set有序
  • unordered_set通过key访问单个元素要比set快,但它通常在遍历元素子集的范围迭
    代方面效率较低。
  • 底层是哈希桶结构
  • 迭代器是单向的,因为底层结构

使用

构造

和set基本一样,这里直接看实例就好了!

	unordered_set<int> s;//无参unordered_set<int> s1(s);//拷贝vector<int> a = { 3,6,9,4,2,10,3 };unordered_set<int> s2(a.begin(),a.end());//迭代区间//初始化列表unordered_set<int> s3 = { 6,7,1,2,4,9,10 };

修改

	unordered_set<int> m;//无参构造vector<int> a = {3,6,9,4,2,10};for (auto b : a){m.insert(b);}m.erase(3);unordered_set<int> m1;m.swap(m1);m.clear();

容量

	unordered_set<int> s3 = { 3,6,9,4,2,10,3 };s3.size();s3.empty();

 迭代器(只有单向)

	unordered_set<int> s3 = { 3,6,9,4,2,10,3 };auto it = s3.begin();while (it != s3.end()){cout << *it << endl;++it;}

查询

auto it = s3.find(3);
s3.count(3);// 0/1

桶操作 

bucket_count()返回桶的个数
bucket_size(n)返回n号桶中有效元素的总个数
bucket(key)返回元素key所在的桶号
	cout << s3.bucket_count() << endl;//统计桶的总数cout << s3.bucket_size(3) << endl;//返回3号桶中的数据个数cout << s3.bucket(3) << endl;//放回3所在的桶号

注意:还有两个容器这里就不过多介绍了,这几个容器使用起来差别不算很大,也比较简单,大家可以点击unordered_multiset和unordered_multimap查看,区别就是multi系列可以存在重复元素

三、unordered系列的性能测试

void test_set2()
{const size_t N = 1000000;unordered_set<int> us;set<int> s;vector<int> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; ++i){//v.push_back(rand()); // N比较大时,重复值比较多//v.push_back(rand()+i); // 重复值相对少v.push_back(i); // 没有重复,有序}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;int m1 = 0;size_t begin3 = clock();for (auto e : v){auto ret = s.find(e);if (ret != s.end()){++m1;}}size_t end3 = clock();cout << "set find:" << end3 - begin3 << "->" << m1 << endl;int m2 = 0;size_t begin4 = clock();for (auto e : v){auto ret = us.find(e);if (ret != us.end()){++m2;}}size_t end4 = clock();cout << "unorered_set find:" << end4 - begin4 << "->" << m2 << 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;}int main()
{test_set2();//test_map1();return 0;
}

大家可以copy到自己的编译器看看其他不同的结果,上述代码的结果如下:

可以看到unordered系列查找的速度确实快啊!因为底层的结构。


如果对你有那么一点帮助,欢迎点赞+收藏哦!

这篇关于【C++STL详解(十三)】unordered系列容器的介绍与使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1121635

相关文章

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

c# checked和unchecked关键字的使用

《c#checked和unchecked关键字的使用》C#中的checked关键字用于启用整数运算的溢出检查,可以捕获并抛出System.OverflowException异常,而unchecked... 目录在 C# 中,checked 关键字用于启用整数运算的溢出检查。默认情况下,C# 的整数运算不会自

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W