【C++进阶】八、STL---unordered_set & unordered_set的介绍及使用

简介: 目录一、unordered系列关联式容器二、unordered_set的介绍及使用2.1 介绍2.2 使用三、unordered_map的介绍及使用3.1 介绍3.2 使用

目录

一、unordered系列关联式容器

二、unordered_set的介绍及使用

2.1 介绍

2.2 使用

三、unordered_map的介绍及使用

3.1 介绍

3.2 使用

一、unordered系列关联式容器

       在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到 logN,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想

 最好的查询是,进行很少的比较次数就能够将元素找到,因此在C++11中,STL又提供了4个unordered系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是其底层结构不同,本文只对 unordered_map 和 unordered_set 进行介绍

      unordered系列容器的底层结构是是哈希桶

1c526e7ab2da4a30952640524573bc5e.png

二、unordered_set的介绍及使用

2.1 介绍unordered_set 的文档介绍:

unordered_set 的文档介绍:

unordered_set - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/unordered_set/unordered_set/?kw=unordered_set


c84f0b96d5fe4cd69923442fe5210849.png

翻译如下:

  1. unordered_set 是不按特定顺序存储唯一元素的容器,允许基于它们的 key 快速检索单个元素
  1. 在 unordered_set 中,元素的值与唯一标识它的 key 同时存在,key 是不可变的,因此,unordered_set 中的元素在容器中不能被修改,但是它可以进行插入和删除
  2. 在内部,unordered_set 中的元素不按任何特定顺序排序,而是根据它们的哈希值插入到相应的桶中,允许直接根据它们的值快速访问单个元素(平均时间复杂度恒定,即常数O(1) )
  3. Unordered_set 容器在通过键访问单个元素时比 set 容器更快,尽管它们在通过元素子集进行范围迭代时通常效率较低
  4. 容器中的迭代器至少是前向迭代器(只支持单向迭代器 ++)

unoc360e062c29145d7906e9f89f584bb21.png

rdered_set 的模板参数有四个:

  1. 第四个模板参数 class Alloc = allocator 是空间配置器,暂时不用理会
  2. 第三个模板参数 class Pred = equal_to 是仿函数,用于判断两个 Key 类型的对象是否相等,因为哈希表中可能存在哈希冲突,所以在同一个索引位置上可能会存储多个元素,Pred 就是用来判断这些元素是否相等的
  3. 第二个模板参数 class Hash = hash是仿函数,是用于指定哈希函数类型,用于将 Key 类型的对象映射为一个无符号整数,这个整数就是哈希表中元素的索引
  4. 第一个模板参数 class Key 是指定哈希表中元素的键类型,是键值对中 key 的类型

使用 unordered_set 要包含头文件:

#include <unordered_set>

2.2 使用

先介绍一下 unordered_set 的前四个成员类型

cbe67aa85f6541fb9c3d7b959b2c042f.png

  • key_type 是第一个模板参数,即(Key),value_type 也是第一个模板参数(Key) ,即键值对 pair --> pair
  • hasher 是第二个模板参数,即(Hash)
  • key_equal 是第三个模板参数,即(Pred)

unordered_set 的使用与 set 非常类似(参考 set 使用即可),但是由于 unordered_set 使用哈希表实现,所以它的效率更高,适用于需要快速查找、插入和删除元素的场景,注意 unordered_set 的迭代器是单向迭代器,只能++

unordered_set 会对插入重复的元素进行去重,即不允许插入相同的值

例如:

#include <iostream>
#include <unordered_set>
using namespace std;
int main() 
{
    unordered_set<int> myset = { 1, 2, 3, 2, 4, 3, 5 }; // 插入重复的元素
    for (auto it = myset.begin(); it != myset.end(); ++it)
    {
        cout << *it << " ";
    }
    return 0;
}
————————————————
版权声明:本文为CSDN博主「枫叶先生」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_64280701/article/details/129545985

运行结果

00f093696c944929a9e40ce0160003ab.png

三、unordered_map的介绍及使用

3.1 介绍

unordered_map 的文档介绍:

unordered_map - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/unordered_map/unordered_map/?kw=unordered_map

7b11d1f91c59426aa508c08ba1cb0632.png

翻译如下:

  1. unordered_map是存储  键值对的关联式容器,其允许通过keys快速的索引到与其对应的 value
  2. 在unordered_map中,键值通常用于惟一地标识元素,而映射值是一个对象,其内容与此键关联。键和映射值的类型可能不同
  3. 在 unordered_map 内部没有对按照任何特定的顺序排序, 为了能在常数范围内找到key所对应的value,unordered_map 将相同哈希值的键值对放在相同的桶中
  4. unordered_map 容器通过 key 访问单个元素要比 map 快,但它通常在遍历元素子集的范围迭代方面效率较低
  5. unordered_maps实现了直接访问操作符( operator[] ),它允许使用 key作为参数直接访问 value
  6. 它的迭代器至少是前向迭代器(只支持单向迭代器 ++)

unordered_map 的模板参数有五个:

aa582109741c4ee4bae8054e272a449b.png

第五个模板参数 class Alloc = allocator 是空间配置器,暂时不用理会

第四个模板参数 class Pred = equal_to 是仿函数,用于判断两个 Key 类型的对象是否相等,因为哈希表中可能存在哈希冲突,所以在同一个索引位置上可能会存储多个元素,Pred 就是用来判断这些元素是否相等的

第三个模板参数 class Hash = hash 是仿函数,是用于指定哈希函数类型,用于将 Key 类型的对象映射为一个无符号整数,这个整数就是哈希表中元素的索引

第二个模板参数 class T 是键值对中 value 的类型

第一个模板参数 class Key 是键值对中 key 的类型

使用 unordered_map 要包含头文件:

#include <unordered_map>

3.2 使用

先介绍一下 unordered_map 的前四个成员类型:

9c8936d72c8f4c768aa3ec1d69b3575b.png

key_type 是第一个模板参数,即(Key)

mapped_type 是第二个模板参数,即(T)

value_type 是键值对 pair>

hasher 是第三个模板参数,即(Hash)

key_equal 是第四个模板参数,即(Pred)

unordered_map 的使用与 map 非常类似(参考map即可),但是由于 unordered_map 使用哈希表实现,所以它的效率更高,适用于需要快速查找、插入和删除键值对的场景,注意 unordered_map 的迭代器是单向迭代器,只能++

还有一点,unordered_map 支持随机访问,即通过 Key 进行访问

a9cc7d518ff94d0da368c62891fda84e.png

这里解释跟 map 的 [] 一致,就不解释了

测试代码

void Test()
{
  unordered_map<string, int> count;
  string str[] = { "苹果", "西瓜", "香蕉", "草莓", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
  for (auto& e : str)
  {
    count[e]++;
  }
  for (auto& kv : count)
  {
    cout << kv.first << ":" << kv.second << endl;
  }
}

运行结果

8372af2d63874b6aa7bfca84c1128399.png

unordered_map 对插入的元素进行去重的方式是根据键(key)是否已存在进行去重的。在 unordered_map 中,每个 key 只能对应一个值,因此如果插入了一个已存在的 key ,那不会进行插入。如果插入的 key 在 unordered_map 中不存在,那么该键值对将被插入到 unordered_map 中


例如:

#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
int main() 
{
    unordered_map<int, string> um;
    um.insert(make_pair(1, "apple"));
    um.insert(make_pair(2, "banana"));
    um.insert(make_pair(3, "cherry"));
    for (auto& it : um)
    {
        cout << it.first << ": " << it.second << endl;
    }
    cout << endl;
    um.insert(make_pair(2, "orange")); // 插入已存在的键key,插入失败
    um.insert(make_pair(4, "orange"));// 插入不存在的键key,会插入新键值对  
    for (auto& e : um)
    {
        cout << e.first << ": " << e.second << endl;
    }
    return 0;
}

运行结果a93b49bbd68840549fb533f728eab257.png

unordered系列的容器底层结构都是哈希表,下一篇介绍哈希表

----------------我是分割线---------------

文章到这里就结束了,下一篇即将更新

相关文章
|
2月前
|
存储 C++ 容器
【C++】map、set基本用法
本文介绍了C++ STL中的`map`和`set`两种关联容器。`map`用于存储键值对,每个键唯一;而`set`存储唯一元素,不包含值。两者均基于红黑树实现,支持高效的查找、插入和删除操作。文中详细列举了它们的构造方法、迭代器、容量检查、元素修改等常用接口,并简要对比了`map`与`set`的主要差异。此外,还介绍了允许重复元素的`multiset`和`multimap`。
35 3
【C++】map、set基本用法
|
2月前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
26 5
|
2月前
|
存储 C++ 容器
【C++】set模拟实现
C++中的`set`是STL提供的一种关联容器,用于存储唯一元素并自动按特定顺序(默认升序)排序。其内部通过红黑树实现,保证了高效的插入、删除和查找操作,时间复杂度均为O(log n)。`set`支持迭代器遍历,提供了良好的数据访问接口。
43 3
|
6月前
|
C++ 容器
【C++】map和set封装
【C++】map和set封装
46 2
|
6月前
|
存储 C++ 容器
【C++】map和set深度讲解(下)
【C++】map和set深度讲解(下)
70 2
|
6月前
|
存储 自然语言处理 Java
【C++】map和set深度讲解(上)
【C++】map和set深度讲解(上)
54 2
|
6月前
|
存储 C++ 容器
|
7月前
|
C++ 容器
C++之set/multiset容器
C++之set/multiset容器
|
7月前
|
编译器 C++
C++模板进阶
C++模板进阶
28 1
|
7月前
|
存储 自然语言处理 C++
【C++航海王:追寻罗杰的编程之路】set|map|multiset|multimap简单介绍
【C++航海王:追寻罗杰的编程之路】set|map|multiset|multimap简单介绍
51 0
【C++航海王:追寻罗杰的编程之路】set|map|multiset|multimap简单介绍