例说数据结构&STL(十)——hash_set/unordered_set

2023-11-13

1 白话hash_set/unordered_set
  这一章节,我们来了解两个新的结构体hash_set和unorderd_set。我将这两者放在一个博文中介绍是因为它们都属于基于哈希表(hash table)构建的数据结构,并且是关键字与键值相等的关联容器。后面我们还会介绍到hash_map与unordered_map两种数据结构,这就好比是set与map的区别了,后面我们再说。
  说到这那到底hash_set与unordered_set哪个更好呢?实际上unordered_set在C++11的时候被引入标准库了,而hash_set并没有,所以建议还是使用unordered_set比较好,这就好比一个是官方认证的,一个是民间流传的。在编译器中,Visual Studio(当然需要支持C++11的版本)库中两个数据结构都有定义,而在gcc/g++中并不支持hash_set。总之,如果想使用这种基于哈希表的关联容器,那么就使用unordered_set就好了。下面我们也将会围绕无序集合容器(unordered_set)讲解,hash_set有对应的公共接口不再细说。
  此外我们来看看unordered_set/hash_set与set有什么区别。首先从内部构建来看,虽然都属于关键字与键值相等的关联容器,但是内部结构大大的不同。set的内部结构是基于红黑树来实现的,所以保证了一个稳定的动态操作时间,查询、插入、删除都是O(logN),最坏和平均都是。而unordered_map如前所述,是哈希表。顺便提一下,哈希表的查询时间虽然是O(1),但是并不是unordered_map查询时间一定比map短,因为实际情况中还要考虑到数据量,而且unordered_map的hash函数的构造速度也没那么快,所以不能一概而论,应该具体情况具体分析。
  第二点从存储方式来看,unordered_set也是一个存储唯一(unique,即无重复)的关联容器(Associative container),但是容器中的元素无特别的秩序关系,该容器允许基于值的快速元素检索,同时也支持正向迭代。在一个unordered_set内部,元素不会按任何顺序排序,而是通过元素值的hash值将元素分组放置到各个桶中,这样就能通过元素值快速访问各个对应的元素(均摊耗时为O(1))。
2 小谈哈希表
  hash_set/unordered_set是哈希表构建的,所以我们在介绍其方法接口前还是有进一步了解一下哈希表的原理。
  哈希表是根据关键码值而进行直接访问的数据结构,通过相应的哈希函数(也称散列函数)处理关键字得到相应的关键码值,关键码值对应着一个特定位置,用该位置来存取相应的信息,这样就能以较快的速度获取关键字的信息。
  比如:现有公司员工的个人信息(包括年龄),需要查询某个年龄的员工个数。由于人的年龄范围大约在[0,200],所以可以开一个200大小的数组,然后通过哈希函数得到key对应的key-value,这样就能完成统计某个年龄的员工个数。而在这个例子中,也存在这样一个问题,两个员工的年龄相同,但其他信息(如:名字、身份证)不同,通过前面说的哈希函数,会发现其都位于数组的相同位置,这里,就涉及到“冲突”。准确来说,冲突是不可避免的,而解决冲突的方法常见的有:开发地址法、再散列法、链地址法(也称拉链法)。而unordered_set内部解决冲突采用的是链地址法,当用冲突发生时把具有同一关键码的数据组成一个链表。下图展示了链地址法的使用:

这里写图片描述

3 unordered_set实战
 3.1 头文件

#include<unordered_set> // hash_set则是#iunclude<hash_set>

using namespace std;

 3.2 其他操作
  由于其常用方法接口和set几乎一样,我不在过多描述,下面只贴出程序样例,一些说明请阅读博文例说数据结构&STL(八)——set.

    unordered_set<int> set_fir; // 默认构造对象

    unordered_set<int> set_sed = { 2, 3, 10, 5, 9 }; //初始化构造

    set_sed.insert(7);          // 插入7,放置在set中位置跟hash构建有关,并不是在尾部

    unordered_set<int>::iterator iter1 = set_sed.lower_bound(2); //返回set中>=2的索引(迭代器),切记非小于2

    unordered_set<int>::iterator iter2 = set_sed.upper_bound(2); //返回set中>2的索引

    set_sed.erase(2); //删除set中元素2

    set_sed.erase(set_sed.begin(), set_sed.end()); //清空整个set

    if (set_sed.find(5) != set_sed.end()) // 查找键值为5的元素
        cout << "exsit" << endl;

    // 正向访问
    unordered_set<int>::iterator iter4;
    for (iter4 = set_sed.begin(); iter4 != set_sed.end(); iter4++)
        cout << *iter4 << endl;

    unordered_set<int>::reverse_iterator iter5; //对应反向迭代器对象
    // 反向访问
    for (iter5 = set_sed.rbegin(); iter5 != set_sed.rend(); iter5++)
        cout << *iter5 << endl;

    set_sed.count(12);     // 返回set中元素的个数,由于set的特殊性,所以结果只有0或者1

    set_sed.swap(set_fir); // 交换所有数据,需要确保set中元素类型相同

    set_sed.clear();       // 清空集合set_sed

    set_sed.size();        // 统计set_sed中元素个数

    set_sed.empty();       // 判断set中是否为空,空则返回1

4 小结
  上面介绍了无序集合容器数据结构特点以及公用的接口。由于集合是基于哈希表构建的数据结构,所以其查询的时间复杂度只有O(1),n为集合中元素的个数。
  以上是个人学习记录,由于能力和时间有限,如果有错误望读者纠正,谢谢!
  转载请注明出处:http://blog.csdn.net/FX677588/article/details/76400389


  参考文献:
  http://www.cnblogs.com/davidgu/p/4998083.html
  http://blog.csdn.net/vevenlcf/article/details/51743058
  http://blog.csdn.net/sdnu111111111/article/details/38658929

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

例说数据结构&STL(十)——hash_set/unordered_set 的相关文章

  • EF Core Group By 翻译支持条件总和

    听说 EF Core 2 1 将支持翻译小组 我感到非常兴奋 我下载了预览版并开始测试它 但发现我在很多地方仍然没有得到翻译分组 在下面的代码片段中 对 TotalFlagCases 的查询将阻止翻译分组工作 无论如何 我可以重写这个以便我
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • vue中tab页签切换导致echarts被压缩的问题

    问题描述 vue中使用tab进行页签切换 echarts图表的宽度设为100 的情况下 图表出现压缩变形的情况 解决方案 1 设置静态的宽度 使用vm单位来设置宽度 vm与 的区别 两个效果大致相同 对于父元素 vm 对于浏览器 2 v i
  • 【华为OD机试真题 JS】一种字符串压缩表示的解压

    标题 一种字符串压缩表示的解压 时间限制 1秒 内存限制 262144K 语言限制 不限 有一种简易压缩算法 针对全部由小写英文字母组成的字符串 将其中连续超过两个相同字母的部分压缩为连续个数加该字母 其他部分保持原样不变 例如 字符串 a
  • 厉害|百度28位离职技术大牛和他们创建的AI公司!

    转自 https www sohu com a 168170780 642762 全球人工智能 拥有十多万AI技术用户 核心用户来自 北大 清华 中科院 麻省理工 卡内基梅隆 斯坦福 哈佛 牛津 剑桥 以及谷歌 腾讯 百度 脸谱 微软 阿里
  • C++(一) --圆的面积

    求圆的面积 include
  • matlab里的CreateQueue,MATLAB 实现队列(FIFO)

    创建 先进先出 FIFO 队列 queue 类的全过程 在本例中 读者应充分注意 构架域 Fields of a structure array 和定义在其上的方法函数 Method function 之间的关系 1 建立类目录 queue
  • rem和em的区别

    相对于font size em针对父元素的font size rem针对于根元素 html 元素的font size
  • LeetCode二维数组例题(原地旋转和对角线遍历)-c语言

    二维数组例题 二维数组 矩阵旋转 原地旋转 对角线遍历 二维数组 矩阵旋转 原地旋转 方法一 四个角是一个循环 引申到四个块是循环 n为偶数时 枚举n2 4个位置 n为奇数时 枚举 n2 1 4个位置 void rotate int mat
  • 吊打面试官系列之:进阶必会Docker命令大全,怎么跟我想象的不一样,简直太easy了。

    Docker必会操作命令 1 引言 2 基本命令 3 镜像命令 3 1 基本操作 3 1 1 查看本地镜像 3 1 2 下载镜像 3 1 3 删除non镜像 3 1 4 制作镜像 3 2 拉取最新镜像 3 3 发布镜像 4 容器命令 4 1
  • React Native_手把手教你做项目(五.下拉刷新RefreshControl&封装自定义Cell)

    接下来我们继续下拉刷新的功能 主要是缓存数据的拼接与后台服务器的配合 把数据最后的id传给后台 后台根据id返回给你新的id之后的数据 因为没有服务器 所以这里的代码仅仅做演示使用 下拉刷新RefreshControl list js im
  • chrome同步或登录报错:Request Canceled

    原因 因为某个接口连接失败造成 可以摁快捷键F12或者点击开发者工具 然后选择network 这里面是该页面所有的收发请求 开始登录 登录的时候要注意network中pending或者报错的接口 然后把域名记录下来 解决方式 安装chrom
  • struct与typedef struct的区别

    typedef是类型定义的意思 typedef struct 是为了使用这个结构体方便 具体区别在于 若struct node 这样来定义结构体的话 在申请node 的变量时 需要这样写 struct node n 若用typedef 可以
  • Makefile---只执行第一行指令解决方法

    在Makefile中将1 c 2 c 3 c分别编译为1 o 2 o 3 o 1 o 1 c gcc c 1 c o 1 o 2 o 2 c gcc c 2 c o 2 o 3 o 3 c gcc c 3 c o 3 o 执行make后只会
  • ajax传输base64,如何通过ajax发送大的base64图像字符串?

    我在通过ajax发送base64图像字符串时遇到问题 当我上传小图片时 它工作正常 但是当我尝试上传大图时 它会产生一个错误 其实我正在创建一个在线可定制的打印Web应用程序 因此 用户可以选择添加文字 图像 我想要的是 当用户按提交but
  • 电子信息工程要考研吗?

    考 如果你的大学或者专业非常牛逼 那当我没说 电子信息工程这个专业比较 坑 学的范围广 内容多 什么模电 数电 C 计算机网络 嵌入式 微机原理 通信原理等等都要学 总之 如果四年下来按部就班的下来 觉得什么都知道 说什么都能和别人扯上几句
  • 机器学习——SVM之python实现数据样本标准化和归一化

    目录 一 标准化和归一化的目的 1 标准化 2 归一化 二 标准化和归一化常用的理论公式 1 归一化 2 标准化 三 python实现SVM样本数据标准化和归一化 1 标准化 2 归一化 本文源代码 机器学习 支持向量机SVM之python
  • Python基础知识

    基础知识 基础知识包括输入输出 变量 数据类型 表达式 运算符这5个方面 1 输入输出 Python有很多函数 后面我们会细讲 但这里先将两个最基本的函数 输入和输出 输出函数print 在前面我们已经用过了 语法就是 print 要输出的
  • 前端案例——轮播图的实现(定时切换图片)

    显示效果为 主页图片每三秒更换一次
  • Windows平台安装GDB调试器

    首先我们需要知道GDB 调试器无法直接安装到 Windows 平台上 如果想在 Windows 系统中使用 GDB 调试器 需要一个中间媒介 常用的就是 MinGW MinGw 全称 Minimalist GNU for Windows 作
  • 关于Keil打开未响应卡死的问题

    跟同事经常互传一些keil工程 由于两人之间的keil的版本不一致 他的keil5 我的keil4 导致我给他的keil4工程他能打开 他给我的keil5工程我用keil4打开就卡死 究其原因是跟工程同目录下的 同名 uvopt文件导致的
  • 例说数据结构&STL(十)——hash_set/unordered_set

    1 白话hash set unordered set 这一章节 我们来了解两个新的结构体hash set和unorderd set 我将这两者放在一个博文中介绍是因为它们都属于基于哈希表 hash table 构建的数据结构 并且是关键字与