unordered_map、unordered_set 底层原理及其相关面试题

目录

unordered_map、unordered_set的底层原理

哈希表的实现

unordered_map 与map的区别?使用场景?

unordered_map、unordered_set的常用函数

 unordered_map map区别和联系


unordered_map、unordered_set的底层原理

unordered_map的底层是一个防冗余的哈希表(采用除留余数法)。哈希表最大的优点,就是把数据的存储和查找消耗的时间大大降低,时间复杂度为O(1);而代价仅仅是消耗比较多的内存。

使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数(一般使用除留取余法),也叫做散列函数),使得每个元素的key都与一个函数值(即数组下标,hash值)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照key为每一个元素“分类”,然后将这个元素存储在相应“类”所对应的地方,称为桶。

但是,不能够保证每个元素的key与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了“冲突”,换句话说,就是把不同的元素分在了相同的“类”之中。 一般可采用拉链法解决冲突:

哈希表的实现

#include <iostream>
#include <vector>
#include <list>
#include <random>
#include <ctime>
using namespace std;const int hashsize = 12;//定一个节点的结构体
template <typename T, typename U>
struct HashNode 
{T _key;U _value;
};//使用拉链法实现哈希表类
template <typename T, typename U>
class HashTable
{
public:HashTable() : vec(hashsize) {}//类中的容器需要通过构造函数来指定大小~HashTable() {}bool insert_data(const T &key, const U &value);int hash(const T &key);bool hash_find(const T &key);
private:vector<list<HashNode<T, U>>> vec;//将节点存储到容器中
};//哈希函数(除留取余)
template <typename T, typename U>
int HashTable<T, U>::hash(const T &key)
{return key % 13;
}//哈希查找
template <typename T, typename U>
bool HashTable<T, U>::hash_find(const T &key)
{int index = hash(key);//计算哈希值for (auto it = vec[index].begin(); it != vec[index].end(); ++it){if (key == it -> _key)//如果找到则打印其关联值{cout << it->_value << endl;//输出数据前应该确认是否包含相应类型return true;}}return false;
}//插入数据
template <typename T, typename U>
bool HashTable<T, U>::insert_data(const T &key, const U &value)
{//初始化数据HashNode<T, U> node;node._key = key;node._value = value;for (int i = 0; i < hashsize; ++i){if (i == hash(key))//如果溢出则把相应的键值添加进链表{vec[i].push_back(node);return true;}}
}int main(int argc, char const *argv[])
{HashTable<int, int> ht;static default_random_engine e;static uniform_int_distribution<unsigned> u(0, 100);long long int a = 10000000;for (long long int i = 0; i < a; ++i)ht.insert_data(i, u(e));clock_t start_time = clock();ht.hash_find(114);clock_t end_time = clock();cout << "Running time is: " << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 <<"ms" << endl;//输出运行时间。system("pause");system("pause");return 0;
}

unordered_map 与map的区别?使用场景?

构造函数:unordered_map 需要hash函数,等于函数;map只需要比较函数(小于函数).

存储结构:unordered_map 采用hash表存储,map一般采用红黑树(RB Tree) 实现。因此其memory数据结构是不一样的。

总体来说,unordered_map 查找速度会比map快,而且查找速度基本和数据数据量大小,属于常数级别;而map的查找速度是log(n)级别。并不一定常数就比log(n)小,hash还有hash函数的耗时,明白了吧,如果你考虑效率,特别是在元素达到一定数量级时,考虑考虑unordered_map 。但若你对内存使用特别严格,希望程序尽可能少消耗内存,那么一定要小心,unordered_map 可能会让你陷入尴尬,特别是当你的unordered_map 对象特别多时,你就更无法控制了,而且unordered_map 的构造速度较慢。

unordered_map、unordered_set的常用函数

unordered_map.begin()     返回指向容器起始位置的迭代器(iterator) 
unordered_map.end()       返回指向容器末尾位置的迭代器 
unordered_map.cbegin()     返回指向容器起始位置的常迭代器(const_iterator) 
unordered_map.cend()      返回指向容器末尾位置的常迭代器 
unordered_map.size()      返回有效元素个数 
unordered_map.insert(key)  插入元素 
unordered_map.find(key)   查找元素,返回迭代器
unordered_map.count(key)  返回匹配给定主键的元素的个数 

 unordered_map map区别和联系

unordered_mapmap 都是 C++ 中的关联容器,用于实现键值对的映射关系。它们的区别和联系如下:

  1. 底层实现不同:unordered_map 的底层实现是哈希表,而 map 的底层实现是红黑树。

  2. 插入、删除、查找等操作的时间复杂度不同:unordered_map 在最坏情况下的时间复杂度为 O(n),而 map 的时间复杂度为 O(log n)。但是,在实际情况下,unordered_map 的性能比 map 更好,因为哈希表通常具有更高的查找速度和更低的冲突率。

  3. 元素的顺序不同:unordered_map 中元素的顺序是无序的,而 map 中元素的顺序是按照键从小到大排序的。

  4. 自定义键类型时的要求不同:unordered_map 要求键类型支持哈希函数和比较函数,而 map 要求键类型支持比较运算符。

  5. 内存占用不同:unordered_map 的内存占用通常比 map 更大,因为哈希表需要使用额外的桶来存储数据。

总之,unordered_mapmap 都是非常有用的关联容器,适用于不同的场景和需求。需要根据实际情况和具体需求来选择使用哪种容器。如果需要按照键的顺序存储和访问元素,或者键类型不支持哈希函数和比较函数,或者希望在最坏情况下仍能保证较好的性能,可以选择使用 map;如果需要快速地进行查找、插入或删除操作,并且可以容忍无序的元素顺序或稍微增加一些内存占用,可以选择使用 unordered_map

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

若依框架部署到服务器后头像资源访问404

排错过程 第一开始以为是代理出问题了 官网给出的解决方案 第一种是用代理后端接口&#xff0c;第二种是重写路径直接访问静态文件 接口通过捕获profile开头的路径/profile/avatar…&#xff0c;转为/home…/avatar找到我们在该路径下的文件 但是我想了一下&#xff0c;我ngin…

Linux——五种IO模型

目录 一IO基本理解 二五种IO模型 1五种IO模型示意图 2同步IO和异步IO 二非阻塞IO 1fcntl 2实现非阻塞IO 三多路复用 1select 1.1定位和作用 1.2介绍参数 1.3编写多路复用代码 1.4优缺点 2poll 2.1作用和定位 2.2介绍参数 2.3修改select代码 3epoll 3.1介绍…

【隐私计算篇】全同态加密应用场景案例(隐私云计算中的大模型推理、生物识别等)

1.题外话 最近因为奖项答辩&#xff0c;一直在忙材料准备&#xff0c;过程非常耗费时间和精力&#xff0c;很难有时间来分享。不过这段时间虽然很忙碌&#xff0c;但这期间有很多新的收获&#xff0c;特别是通过与领域内专家的深入交流和评审过程&#xff0c;对密码学和隐私计算…

【汇编语言】第一个程序(四)—— 谁在幕后启动程序 : 探讨可执行文件的装载与执行

文章目录 前言1. 可执行文件的加载与运行1.1 DOS中的程序加载过程1.2 问题1&#xff1a;谁加载了1.exe&#xff1f;1.3 问题2&#xff1a;程序运行结束后的返回过程1.4 操作系统的外壳1.5 回答问题1和问题21.6 汇编程序执行的完整历程 2. 使用Debug加载与跟踪1.exe2.1 Debug的加…

Unreal Engine 5 C++(C#)开发:使用蓝图库实现插件(一)认识和了解Build.cs

目录 引言 一、创建一个C插件TextureReader插件 二、Build.cs文件 三、ModuleRules 四、TextureReader插件的构造 4.1ReadOnlyTargetRules的作用 4.2TextureReaderd的构造调用 4.3设置当前类的预编译头文件的使用模式 4.4PublicIncludePaths.AddRange与PrivateInclude…

SELS-SSL/TLS

一、了解公钥加密&#xff08;非对称加密&#xff09; 非对称加密中&#xff0c;用于加密数据的密钥与用于解密数据的密钥不同。私钥仅所有者知晓&#xff0c;而公钥则可自由分发。发送方使用接收方的公钥对数据进行加密&#xff0c;数据仅能使用相应的私钥进行解密。 你可以将…

STM32FreeRTOS 使用QSPI驱动nandFlash

STM32FreeRTOS 使用QSPI驱动nandFlash 不清楚为什么STM32同时打开3个以上的音频文件时会出现播放问题&#xff0c;所以更换方案。因为SRAM的内存空间过小&#xff0c;用于存储音频文件不适合&#xff0c;所以使用大小为128MByte的nandFlash。 nandFlash使用华邦的W25N01GVZEI…

vscode的一些使用心得

问题1&#xff1a;/home目录空间有限 连接wsl或者remote的时候&#xff0c;会在另一端下载一个.vscode-server&#xff0c;vscode的插件都会安装进去&#xff0c;导致空间增加很多&#xff0c;可以选择更换这个文件的位置 参考&#xff1a;https://blog.csdn.net/weixin_4389…

1Panel应用商店开源软件累计下载突破200万次!

2024年10月23日&#xff0c;1Panel应用商店内开源软件累计下载突破200万次。 1Panel&#xff08;github.com/1Panel-dev/1Panel&#xff09;是一款现代化、开源的Linux服务器运维管理面板&#xff0c;它致力于通过开源的方式&#xff0c;帮助用户简化建站与运维管理流程。 为…

基于MATLAB多参数结合火焰识别系统

一、课题介绍 本设计为基于MATLAB的火焰烟雾火灾检测系统。传统的采用颜色的方法&#xff0c;误识别大&#xff0c;局限性强。结合火焰是实时动态跳跃的&#xff0c;采用面积增长率&#xff0c;角点和圆形度三个维度相结合的方式判断是否有火焰。该设计测试对象为视频&#xf…

利用摄像机实时接入分析平台LiteAIServer视频智能分析软件进行视频监控:过亮过暗检测算法详解

视频监控作为一种重要的安全和管理工具&#xff0c;广泛应用于各个领域&#xff0c;如安全监控、交通监管、员工监管、公共场所监控等。然而&#xff0c;在实际应用中&#xff0c;视频监控系统经常面临各种挑战&#xff0c;其中之一便是视频画面过亮或过暗的问题。过亮过暗检测…

python画图|坐标轴比例设置方法

【1】引言 在前序学习进程中&#xff0c;我们通过ax.set_box_aspect()函数掌握了坐标轴等比例设置方法。 担当我在回顾以前的学习文章时&#xff0c;发现ax.axis()函数也可以设置坐标轴比例&#xff0c;比如下述文章&#xff0c;文章可通过点击链接直达&#xff1a; python画…

[前端][基础]JavaScript

1&#xff0c;JavaScript简介 JavaScript 是一门跨平台、面向对象的脚本语言&#xff0c;而Java语言也是跨平台的、面向对象的语言&#xff0c;只不过Java是编译语言&#xff0c;是需要编译成字节码文件才能运行的&#xff1b;JavaScript是脚本语言&#xff0c;不需要编译&…

用于文档理解的局部特征

本文介绍了一种名为DocFormerv2的多模态Transformer模型&#xff0c;它专为视觉文档理解&#xff08;VDU&#xff09;而设计。该模型可以处理视觉、语言和空间特征&#xff0c;利用编码器-解码器架构&#xff0c;并通过不对称地使用新颖的无监督任务进行预训练&#xff0c;以促…

Chromium127编译指南 Linux篇 - 额外环境配置(五)

引言 在成功获取 Chromium 源代码后&#xff0c;接下来我们需要配置适当的编译环境&#xff0c;以便顺利完成开发工作。本文将详细介绍如何设置 Python 和相关的开发工具&#xff0c;以确保编译过程无碍进行。这些配置步骤是开发 Chromium 的必要准备&#xff0c;确保环境设置…

HTTP相关返回值异常原因分析,第二部分

今天我们讲讲HTTP相关返回值异常如何解决&#xff08;实例持续更新中&#xff09; 一、4xx状态码 这些状态码表示请求有问题&#xff0c;通常是由于客户端的错误引起的。 1.1 400 Bad Request: 请求格式不正确&#xff0c;服务器无法理解。 状态码400的含义&#xff1a; …

.NET内网实战:通过白名单文件反序列化漏洞绕过UAC

01阅读须知 此文所节选自小报童《.NET 内网实战攻防》专栏&#xff0c;主要内容有.NET在各个内网渗透阶段与Windows系统交互的方式和技巧&#xff0c;对内网和后渗透感兴趣的朋友们可以订阅该电子报刊&#xff0c;解锁更多的报刊内容。 02基本介绍 03原理分析 在渗透测试和红…

Spring Boot 实现文件分片上传和下载

文章目录 一、原理分析1.1 文件分片1.2 断点续传和断点下载1.2 文件分片下载的 HTTP 参数 二、文件上传功能实现2.1 客户端(前端)2.2 服务端 三、文件下载功能实现3.1 客户端(前端)3.2 服务端 四、功能测试4.1 文件上传功能测试4.2 文件下载功能实现 参考资料 完整案例代码&…

【数据结构】-数组

数组 特点&#xff1a; 数组的地址连续&#xff0c;可以通过下标获取数据。 1. 数组扩容 步骤&#xff1a; $1. 创建一个比原来数组更长的新数组 $2. 让原来数组当中的数据依次复制到新数组当中 $3. 让arr指向新数组&#xff0c;原数组空间释放 2. 数组插入 2.1 最后位置…