数据结构进阶 unordered_set unordered_map的使用

news2024/10/6 14:24:45

作者:@小萌新
专栏:@数据结构进阶
作者简介:大二学生 希望能和大家一起进步!
本篇博客简介:介绍高阶数据结构 unorder_set unorder_map的使用

unorder_set unorder_map

  • unordered系列关联式容器
  • unordered_set介绍
  • unordered_set的使用
    • unordered_set的定义方式
      • 方式一 构造一个某类型空容器
      • 方式二 拷贝构造某同类型容器的复制品
      • 方式三 使用迭代器拷贝构造一段内容
    • unordered_set的接口函数
      • 展示去重和范围for遍历
      • 展示直接去重
      • 展示迭代器遍历
      • 展示查找计数交换等
      • 展示交换容器
      • unordered_multiset
  • unordered_map的介绍
  • unordered_map的使用
    • unordered_map的定义方式
      • 方式一 构造一个某类型的空容器
      • 方式二 拷贝构造某类型容器的复制品
      • 方式三 使用迭代器拷贝构造某一段内容
    • unordered的接口函数
      • 展示去重和范围for遍历
      • 展示直接去重
      • 展示迭代器遍历
      • 展示查找
      • 展示【】运算符
      • 展示计数清除等
      • unordered_multimap

unordered系列关联式容器

在C++98中 STL提供了底层为红黑树的一系列关联式容器 在查询时效率可以达到Log(N)

即在最差的情况下 查询红黑树的高度次 这个时候的效率也不太理想

最好的查询是 通过很少的比较次数就能够将被查询元素找到

因此 在C++11中 STL又提供了四个unordered系列的关联式容器

这四个容器与map和set的用法相似 但底层结构不同

unordered_set介绍

  1. unordered_set是不按照特定顺序存储键值的关联式容器 其允许通过键值快速索引到对应元素
  2. 在unordered_set中 元素的值也是唯一标识它的key
  3. 在内部 unordered_set中的元素没有按照任何特定顺序排列 为了能在常数时间内找到key unordered_set将相同哈希值的键值放在桶中
  4. unordered_set查找单个元素的效率比set快 但是它遍历元素子集的范围迭代效率差
  5. 它的迭代器至少是前向迭代器

unordered_set的使用

unordered_set的定义方式

方式一 构造一个某类型空容器

	unordered_set<int> us1; // 构造一个int类型的空容器

方式二 拷贝构造某同类型容器的复制品

	unordered_set<int> us2(us1); // 构造某类型容器的复制品

方式三 使用迭代器拷贝构造一段内容

	string s1("hello world");
	unordered_set<char> us3(s1.begin(), s1.end()); // 使用string的迭代器拷贝构造

unordered_set的接口函数

在这里插入图片描述
迭代器相关函数如下
在这里插入图片描述

使用示例如下

展示去重和范围for遍历

	unordered_set<int> us1; // 构造一个int类型的空容器
	us1.insert(3);
	us1.insert(3);
	us1.insert(5);
	us1.insert(1);
	us1.insert(7);
	us1.insert(8);
	for (auto x: us1)
	{
		cout << x << endl;
	}

我们使用unordered_set容器 并且插入多组重复数据 之后使用范围for遍历 达到一个去重的效果

注意 这里和set的区别是不会排序

展示直接去重

	unordered_set<int> us1; // 构造一个int类型的空容器
	us1.insert(3);
	us1.insert(3);
	us1.insert(5);
	us1.insert(1);
	us1.insert(7);
	us1.insert(8);
	for (auto x : us1)
	{
		cout << x << " ";
	}
	cout << endl;

	us1.erase(3);
	for (auto x : us1)
	{
		cout << x << " ";
	}
	cout << endl;

我们调用erase删除我们想要删除的值 并且再遍历一遍容器

在这里插入图片描述
我们可以发现 3被删除了

那么假如我们连续两次删除3会发生什么呢?

在这里插入图片描述

展示迭代器遍历

代码如下

	unordered_set<int> us1; // 构造一个int类型的空容器
	us1.insert(3);
	us1.insert(3);
	us1.insert(5);
	us1.insert(1);
	us1.insert(7);
	us1.insert(8);
	unordered_set<int>::iterator it = us1.begin();
	while (it != us1.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;

展示效果如下

在这里插入图片描述

展示查找计数交换等

	unordered_set<int> s1; // 构造一个int类型的空容器
	s1.insert(1);
	s1.insert(3);
	s1.insert(5);
	s1.insert(3);
	s1.insert(4);
	s1.insert(9);
	s1.insert(7);
	s1.insert(4);


	cout << s1.count(3) << endl;
	cout << s1.count(2) << endl;
	cout << s1.size() << endl;
	s1.clear();
	cout << s1.size() << endl;
	cout << s1.empty() << endl;

我们可以发现查找 3 2 出现的次数

s1的大小 清空后的大小 以及s1是否为空

在这里插入图片描述

展示交换容器

	unordered_set<int> s1; // 构造一个int类型的空容器
	s1.insert(1);
	s1.insert(3);
	s1.insert(5);
	s1.insert(3);
	s1.insert(4);
	s1.insert(9);
	s1.insert(7);
	s1.insert(4);
	unordered_set<int> s2;
	cout << s2.size() << endl;
	cout << s1.size() << endl;
	s2.swap(s1);

	cout << s2.size() << endl;
	cout << s1.size() << endl;

我们可以发现 交换后两个容器的大小发生了变化

unordered_multiset

unordered_multiset和unordered_set的底层实现都是相同的 接口函数也十分类似

它们之间最大的区别就是 unordered_multiset中允许键值对冗余

	unordered_multiset<int> us1; // 构造一个int类型的空容器
	us1.insert(3);
	us1.insert(3);
	us1.insert(5);
	us1.insert(1);
	us1.insert(7);
	us1.insert(8);
	for (auto x : us1)
	{
		cout << x << " ";
	}
	cout << endl;

我们可以看到运行结果有冗余的键值

在这里插入图片描述
由于multiset容器允许键值冗余,因此两个容器中成员函数find和count的意义也有所不同

成员函数find功能
unordered_set容器返回键值为val的元素的迭代器
unordered_multiset容器返回底层哈希表中第一个找到的键值为val的元素的迭代器
成员函数count功能
unordered_set容器键值为val的元素存在则返回1,不存在则返回0(find成员函数可替代)
unordered_multiset容器返回键值为val的元素个数(find成员函数不可替代)

unordered_map的介绍

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

unordered_map的使用

unordered_map的定义方式

方式一 构造一个某类型的空容器

	unordered_map<int, int> um1; // 构造一个某类型的空容器

方式二 拷贝构造某类型容器的复制品

	unordered_map<int, int> um2(um1); // 拷贝构造某类型容器的复制品

方式三 使用迭代器拷贝构造某一段内容

	unordered_map<int, int> um3(um1.begin(), um1.end());// 使用迭代器拷贝构造某一段内容

unordered的接口函数

在这里插入图片描述
除了上述接口函数外 unordered_map还提供了一个功能十分强大的接口函数【】

  • 若当前容器中已有键值为key的键值对 则返回该键值对于value的引用
  • 若当前容器中无键值为key的键值对 则先插入键值对<key,value()> 之后返回该键值对于value的引用

迭代器相关函数如下

在这里插入图片描述
使用示例如下

展示去重和范围for遍历

	unordered_map<int, int> um1; // 构造一个某类型的空容器
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(5, 5));
	um1.insert(make_pair(1, 1));
	um1.insert(make_pair(7, 7));
	um1.insert(make_pair(8, 8));
	for (auto x : um1)
	{
		cout << x.first << " ";
	}
	cout << endl;

我们使用unordered_map容器 并且插入多组重复数据之后使用范围for遍历 达到一个去重的效果

注意 这里和map的区别是不会排序

在这里插入图片描述

展示直接去重

	unordered_map<int, int> um1; // 构造一个某类型的空容器
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(5, 5));
	um1.insert(make_pair(1, 1));
	um1.insert(make_pair(7, 7));
	um1.insert(make_pair(8, 8));
	for (auto x : um1)
	{
		cout << x.first << " ";
	}
	cout << endl;

	um1.erase(3);
	for (auto x : um1)
	{
		cout << x.first << " ";
	}
	cout << endl;

我们调用erase删除我们想要删除的key值 并且再遍历一遍容器

在这里插入图片描述
我们可以发现3被删除了

那么假如我们连续两次删除3会发生什么呢?

在这里插入图片描述

展示迭代器遍历

代码如下

	unordered_map<int, int> um1; // 构造一个某类型的空容器
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(5, 5));
	um1.insert(make_pair(1, 1));
	um1.insert(make_pair(7, 7));
	um1.insert(make_pair(8, 8));

	auto it = um1.begin();
	while (it != um1.end())
	{
		cout << it->first << " ";
		it++;
	}

	cout << endl;

展示效果如下

在这里插入图片描述

展示查找

unordered_map的查找是根据key值在unordered_map中查找 有两种结果

  • 如果找到了则返回对应的迭代器
  • 如果找不到则返回end迭代器

代码和演示效果如下

	unordered_map<int, int> um1; // 构造一个某类型的空容器
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(5, 5));
	um1.insert(make_pair(1, 1));
	um1.insert(make_pair(7, 7));
	um1.insert(make_pair(8, 8));

	auto it = um1.find(3);
	auto it2 = um1.find(4);

	if (it != um1.end())
	{
		cout << it->first << endl;
	}
	if (it2 != um1.end())
	{
		cout << it2->first << endl;
	}

在这里插入图片描述

我们可以发现 确实符合上面的规则

展示【】运算符

首先我们明确下它的规则

  • 如果key不在unordered_map中 则使用【】会插入键值对 然后返回该键值对中value的引用
  • 如果key在unordered_map中则会返回键值为K的元素的value的引用

测试代码和结果如下

	unordered_map<int, int> um1; // 构造一个某类型的空容器
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(5, 5));
	um1.insert(make_pair(1, 1));
	um1.insert(make_pair(7, 7));
	um1.insert(make_pair(8, 8));
	um1[3] = 20;
	um1[9] = 9;

	auto it = um1.find(3);
	cout << it->second << endl;

	for (auto x : um1)
	{
		cout << x.first << " ";
	}

在这里插入图片描述
我们可以看到 进行了

	um1[3] = 20;
	um1[9] = 9;

这两步操作之后

key值为3的value变成了20

多了一个key值为9的元素

展示计数清除等

这里很简单 直接看代码和演示结果就可以

	unordered_map<int, int> um1; // 构造一个某类型的空容器
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(5, 5));
	um1.insert(make_pair(1, 1));
	um1.insert(make_pair(7, 7));

	cout << um1.size() << endl;
	um1.clear();
	cout << um1.size() << endl;

在这里插入图片描述

unordered_multimap

unordered_multimap和unordered_map的底层实现都是相同的 接口函数也十分类似

它们之间最大的区别就是 unordered_multimap中允许键值对冗余

代码和演示结果如下

	unordered_multimap<int, int> um1; // 构造一个某类型的空容器
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(3, 3));
	um1.insert(make_pair(5, 5));
	um1.insert(make_pair(1, 1));
	um1.insert(make_pair(7, 7));

	for (auto x : um1)
	{
		cout << x.first << " ";
	}

在这里插入图片描述
由于unordered_multimap容器允许键值对的键值冗余 因此该容器中成员函数find和count的意义与unordered_map容器中的也有所不同

成员函数find功能
unordered_map容器返回键值为key的键值对的迭代器
unordered_multimap容器返回底层哈希表中第一个找到的键值为key的键值对的迭代器
成员函数count功能
unordered_map容器键值为key的键值对存在则返回1,不存在则返回0(find成员函数可替代)
unordered_multimap容器返回键值为key的键值对的个数(find成员函数不可替代)

此外由于unordered_multimap容器允许键值对冗余 因此【】操作符可能会产生歧义 因此在unordered_multimap容器中并未实现之

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

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

相关文章

微信小程序流量主提升ecpm的一些方法

本篇文章主要讲解:微信小程序流量主提升ecpm的一些方法 日期:2023年1月19日 作者:任聪聪 一、对ecpm的疑问和科普 什么是ecpm ecpm就是千次广告曝光收入,是一个预估的价格,而不是额定的,他是随着曝光度,用户点击度,页面访问数来决定的。 ecpm为什么会低? 微信官方…

KaiwuDB 数据服务平台 1.0 产品详解

大家好&#xff0c;今天我分享的是 KaiwuDB 数据服务平台&#xff08;KDP&#xff09;&#xff0c;一款由我们独立自主研发&#xff0c;以 KaiwuDB 为核心的数据服务产品。KDP 产品建设目标是实现数据的云边端的一体化治理&#xff0c;提供一套完整的全生命周期服务。接下来我将…

2.5、线程概念和多线程模型

整体框架 1、什么是线程&#xff0c;为什么要引入线程&#xff1f; 还没有引入进程之前&#xff0c;各个程序只能串行执行 进程是程序的一次执行过程&#xff0c;但这些功能显然不可能是由一个程序顺序处理就能实现的 有的进程可能需要 “同时” 做很多事&#xff0c;而传统的…

伯俊ERP与金蝶云星空对接集成连通应收单新增

伯俊ERP与金蝶云星空对接集成表头表体组合查询连通应收单新增(应收单-标准应收单&#xff08;KD应收单销售退)数据源系统:伯俊ERP未来&#xff0c;伯俊科技也会砥砺前行&#xff0c;不断为品牌提供更全面的零售终端致胜利器。伯俊科技始终坚持创新发展&#xff0c;探索大零售行…

【IDEA】自动部署SpringBoot Jar包到远程服务器并通过脚本启动jar

【IDEA】自动部署SpringBoot Jar包到远程服务器并通过脚本启动jar 文章目录 前言一.Deployment使用二.ssh使用三.启动脚本 前言 IDEA版本: 2019.3 一.Deployment使用 IDRA原生的Deployment不需要离开idea就可以直接将项目部署到远程运行&#xff0c;同时拥有远程视图窗口…

高并发系统设计 --计数服务抽离

传统计数 模糊计数 Cache DB。写Cache&#xff0c;批量刷新DB。 有一个写请求&#xff0c;我们就写cache&#xff0c;写一个在cache中1&#xff0c;buffer记一个&#xff0c;差不多&#xff08;buffer满了&#xff0c;时间到了&#xff09;写一次DB&#xff0c;丢数据也就丢…

JVM快速入门学习笔记(二)

临近过年&#xff0c;事太多&#xff0c;学习效率也好低&#xff0c;最近已经好久没搞学习了&#xff0c;发篇简单的学习笔记意思下吧 5. 沙箱安全机制 Java安全模型的核心就是Java沙箱&#xff08;sandbox&#xff09;&#xff0c;什么是沙箱&#xff1f;沙箱是一个限制程序运…

Oracle 12c多租户特性详解:从Schema到PDB的变化与隔离

CDB和PDB的职责分离一些数据库管理员管理整个CDB&#xff0c;而另一些管理员管理单个的pdb。.管理整个CDB的dba作为普通用户连接到CDB&#xff0c;管理整个CDB和根的属性&#xff0c;以及pdb的一些属性。例如&#xff0c;这些dba可以创建、拔出、插入和删除pdb。它们还可以为根…

【c语言】文件操作详解

主页&#xff1a;114514的代码大冒险 qq:2188956112&#xff08;欢迎小伙伴呀hi✿(。◕ᴗ◕。)✿ &#xff09; Gitee&#xff1a;庄嘉豪 (zhuang-jiahaoxxx) - Gitee.com 目录 前言 一、文件是什么 二、文件的打开和关闭 1.文件指针 2.文件的打开和关闭 三&#xff0c;文件的顺…

《计算机体系结构量化研究方法》 B.4 虚拟存储器 笔记

B.4 虚拟存储器 一、基本概念 1、虚拟存储器把物理存储器划分成块以后分配给不同的进程&#xff1b;采用一种保护机制来限制各个进程&#xff0c;使其仅能访问属于自己的块。 2、重定位机制允许同一程序在物理存储器中的任意位置运行。 3、页和段用于块&#xff0c;缺页错误…

SSM框架整合入门案例

文章目录SSM整合案例1&#xff0c;SSM整合1.1 流程分析1.2 整合配置步骤1&#xff1a;创建Maven的web项目步骤2:添加依赖步骤3:创建项目包结构步骤4:创建SpringConfig配置类步骤5:创建JdbcConfig配置类步骤6:创建MybatisConfig配置类步骤7:创建jdbc.properties步骤8:创建Spring…

《Buildozer打包实战指南》第七节 常见的打包问题

目录 无法访问xxx网址&#xff0c;连接超时 目标路径xxx已经存在&#xff0c;并且不是一个空目录 每次打包时间都要很久 待更新 在打包过程中难免会碰到一些问题&#xff0c;在本节&#xff0c;笔者会把自己碰到的一些问题的解决方案写出来&#xff0c;好让读者节省时间。 …

KaiwuDB CTO 魏可伟:1.0 时序数据库技术解读

大家好&#xff0c;首先非常感谢大家参与本次 KaiwuDB 1.0 系列产品发布会。作为国内数据库新生品牌力量&#xff0c;KaiwuDB 是浪潮集团控股的数据库企业&#xff0c;我们聚焦在工业物联网、数字能源、交通车联网、智慧产业等快速发展的重要领域&#xff0c;希望为各大行业客户…

06技术太卷我学APEX-技术太卷我学APEX

06技术太卷我学APEX-技术太卷我学APEX 0 概述 自学APEX第7天&#xff0c;用APEX做了一个自学的笔记APP&#xff0c;名称就叫《技术太卷我学APEX》 1 登录页面 登录页面设置&#xff1a;就改了下名称和加上了测试账号。 登录页面效果&#xff1a; 这个是 APEX功能页面之一…

前端面试题合集-第一篇

前端面试题合集-第一篇 &#x1f514;每周不定时更新&#xff01; ⛄️不要让自己失去竞争力&#xff01; ☀️哪里都不是避风港&#xff0c;保持竞争力! 1. CSS选择器的优先级 !important>内联>id选择器>类选择器>标签选择器>通配符选择器>继承 在同一…

Java IO流补充 - Properties - IO流框架commons-io

文章目录IO流补充知识Properties结合IO流集合IO流框架IO流补充知识 Properties结合IO流集合 我们先来认识Properties属性集对象 Properties其实就是一个Map集合&#xff0c;但是我们一般不会当集合使用&#xff0c;因为HashMap更好用。 Properties核心作用: 属性文件&#xf…

设计模式_行为型模式 -《观察者模式》

设计模式_行为型模式 -《观察者模式》 笔记整理自 黑马程序员Java设计模式详解&#xff0c; 23种Java设计模式&#xff08;图解框架源码分析实战&#xff09; 概述 定义 观察者模式&#xff0c;又被称为发布-订阅&#xff08;Publish / Subscribe&#xff09;模式&#xff0c…

RSA与证书

这篇文章详细讲述一下RSA与证书的相关内容。内容有点多&#xff0c;但都是干货。 一、RSA算法 1.1简介 RSA算法是由美国三位科学家Rivest、Shamir和Adleman于1976年提出并在1978年正式发表的公开密码算 法&#xff0c;其命名取自三位创始人名字的首字母缩写。该算法基于数论…

CSS 计数器

CSS 计数器 CSS 计数器可让你根据内容在文档中的位置调整其显示的外观。例如&#xff0c;你可以使用计数器自动为网页中的标题编号&#xff0c;或者更改有序列表的编号。 本质上 CSS 计数器是由 CSS 维护的变量&#xff0c;这些变量可能根据 CSS 规则跟踪使用次数以递增或递减…

【Git】利用 GIT 做版本控制

目录 写在前面 备份方法 效果展示 写在前面 在做项目开发时&#xff0c;不免需要进行版本更替或者使增加新功能等&#xff0c;这时很重要的环节是对版本进行备份&#xff0c;以便在新版本开发过程中出现问题&#xff0c;而当工程文件过大时&#xff0c;在对文件备份时需要占…