【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

相关文章

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行