首页 > 编程语言 >第4章 C++ STL无序关联式容器总结

第4章 C++ STL无序关联式容器总结

时间:2022-10-16 09:35:27浏览次数:57  
标签:容器 存储 map STL 无序 C++ 键值 unordered

除了序列式容器关联式容器之外,C++ 11 标准库又引入了一类容器,即无序关联式容器。 无序关联式容器,又称哈希容器

  • 和关联式容器一样,此类容器存储的也是键值对元素;不同之处在于,关联式容器默认情况下会对存储的元素做升序排序,而无序关联式容器不会。 
  • 和其它类容器相比,无序关联式容器擅长通过指定键查找对应的值,而遍历容器中存储元素的效率不如关联式容器

C++ STL无序容器(哈希容器)是什么?

C++ STL 底层采用哈希表实现无序容器时,会将所有数据存储到一整块连续的内存空间中,并且当数据存储位置发生冲突时,解决方法选用的是“链地址法”(又称“开链法”)

基于底层实现采用了不同的数据结构,因此和关联式容器相比,无序容器具有以下 2 个特点:

  • 无序容器内部存储的键值对是无序的各键值对的存储位置取决于该键值对中的键
  • 和关联式容器相比,无序容器擅长通过指定键查找对应的值(平均时间复杂度为 O(1))但对于使用迭代器遍历容器中存储的元素,无序容器的执行效率则不如关联式容器

和关联式容器一样,无序容器只是一类容器的统称,其包含有 4 个具体容器,分别为 unordered_mapunordered_multimapunordered_set 以及 unordered_multiset

表 1 无序容器种类
无序容器功能
unordered_map  存储键值对 <key, value> 类型的元素,其中各个键值对键的值不允许重复,且该容器中存储的键值对是无序的
unordered_multimap 和 unordered_map 唯一的区别在于,该容器允许存储多个键相同的键值对
unordered_set 不再以键值对的形式存储数据,而是直接存储数据元素本身(当然也可以理解为,该容器存储的全部都是键 key 和值 value 相等的键值对,正因为它们相等,因此只存储 value 即可)。另外,该容器存储的元素不能重复,且容器内部存储的元素也是无序的。
unordered_multiset 和 unordered_set 唯一的区别在于,该容器允许存储值相同的元素。

C++ 11 标准的 STL 中,在已提供有 4 种关联式容器的基础上,又新增了各自的“unordered”版本(无序版本、哈希版本),提高了查找指定元素的效率

总的来说,实际场景中如果涉及大量遍历容器的操作,建议首选关联式容器;反之,如果更多的操作是通过键获取对应的值,则应首选无序容器

#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;

int main()
{
    //创建并初始化一个 unordered_map 容器,其存储的 <string,string> 类型的键值对
    std::unordered_map<std::string, std::string> my_uMap{
            {"keras教程","python深度学习"},
            {"深度学习教程","动手学习深度学习"},
            {"Java教程","廖雪峰java教程"} };
    //查找指定键对应的值,效率比关联式容器高
    string str = my_uMap.at("keras教程");
    cout << "str = " << str << endl;

    //使用迭代器遍历哈希容器,效率不如关联式容器
    for (auto iter = my_uMap.begin(); iter != my_uMap.end(); ++iter)
    {
        //pair 类型键值对分为 2 部分
        cout << iter->first << " " << iter->second << endl;
    }
    return 0;
}

C++ STL unordered_map容器用法详解

unordered_map 容器和 map 容器一样,以键值对(pair类型)的形式存储数据,存储的各个键值对的键互不相同且不允许被修改。但由于 unordered_map 容器底层采用的是哈希表存储结构,该结构本身不具有对数据的排序功能,所以此容器内部不会自行对存储的键值对进行排序。 

unordered_map 容器在<unordered_map>头文件中,并位于 std 命名空间中。因此,如果想使用该容器,代码中应包含如下语句:

#include <unordered_map>
using namespace std;

unordered_map 容器模板的定义如下所示:

template < class Key,                        //键值对中键的类型
           class T,                          //键值对中值的类型
           class Hash = hash<Key>,           //容器内部存储键值对所用的哈希函数
           class Pred = equal_to<Key>,       //判断各个键值对键相同的规则
           class Alloc = allocator< pair<const Key,T> >  // 指定分配器对象的类型
           > class unordered_map;

以上 5 个参数中,必须显式给前 2 个参数传值,并且除特殊情况外,最多只需要使用前 4 个参数,各自的含义和功能如表 1 所示。 

表 1 unordered_map 容器模板类的常用参数
参数含义
<key,T> 前 2 个参数分别用于确定键值对中键和值的类型,也就是存储键值对的类型。
Hash = hash<Key> 用于指明容器在存储各个键值对时要使用的哈希函数,默认使用 STL 标准库提供的 hash<key> 哈希函数。注意,默认哈希函数只适用于基本数据类型(包括 string 类型),而不适用于自定义的结构体或者类
Pred = equal_to<Key> 要知道,unordered_map 容器中存储的各个键值对的键是不能相等的,而判断是否相等的规则,就由此参数指定。默认情况下,使用 STL 标准库中提供的 equal_to<key> 规则,该规则仅支持可直接用 == 运算符做比较的数据类型

总的来说,当无序容器中存储键值对的键为自定义类型时,默认的哈希函数 hash 以及比较函数 equal_to 将不再适用,只能自己设计适用该类型的哈希函数和比较函数,并显式传递给 Hash 参数和 Pred 参数。  

创建C++ unordered_map容器的方法:  

通过调用 unordered_map 模板类的默认构造函数,可以创建空的 unordered_map 容器。比如:

std::unordered_map<std::string, std::string> umap;

  

  

标签:容器,存储,map,STL,无序,C++,键值,unordered
From: https://www.cnblogs.com/zjuhaohaoxuexi/p/16795482.html

相关文章

  • 掌握C++的左值引用和初识右值引用
    一、引用和指针的区别?1、左值引用和右值引用2、引用的实例 1、引用是更安全的指针(1)安全性:引用是必须初始化的,指针可以不初始化。 引用能够保证一定能够引用到一个......
  • C++内存泄漏
        程序在堆中申请的动态内存,在程序使用完成时没有得到及时的释放。当这些变量的生命周期已结束时,该变量在堆中所占用的内存未能得到释放,从而就导致了堆中可使用的......
  • JSTL下载jar包和放到项目中
    JSTL一、下载jar包从Apache的标准标签库下载网址:Indexof/dist/jakarta/taglibs/standard/binaries(apache.org)选择jakarta-taglibs-standard-1.1.2进行下载......
  • C++大端与小端
    字节序:字节顺序又称端序或尾序(Endianness),在计算机科学领域中,指电脑内存中或在数字通信链路中,组成多字节的字的字节的排列顺序。在几乎所有的机器上,多字节对象都被存储为连......
  • C/C++ 变量的四种存储类型
    所有的数据都有两种类型数据类型:如int,float等存储类型:总共有四种存储类型的变量,分别为自动变量(auto)、静态变量(static)、外部变量(extern)以及寄存器变量(register)。(1......
  • 【C++】统计string里面出现的字符的个数(使用count函数)
    题目:给出一个string字符串,统计里面出现的字符的个数解决方案:使用算法库<algorithm>里面的count函数(不是s.count()!!count是单独作为一个函数,而不是作为一个方法),使用方法是......
  • vs code c++ 中文乱码问题
    解决方法:在vscode下方点击编码点击重新编码,改成GB2312同时,对tasks.json中的配置,进行更改......
  • c++游戏客户端修改记录
    c++游戏客户端编译原代码是基于WTL8.0的,可能是vs2005版本编译。本次使用vs2013升级,之后主要遇到的错误记录在此,最后编译成功了项目中已经引入了wtl8的头文件到include......
  • C++关键字之likely和unlikely
    什么是likely和unlikely既然程序是我们程序员所写,在一些明确的场景下,我们应该比CPU和编译器更了解哪个分支条件更有可能被满足。我们是否可将这一先验知识告知编译器和CPU......
  • C++ Primer Plus学习笔记之开始学习C++
    前言个人觉得学习编程最有效的方法是阅读专业的书籍,通过阅读专业书籍可以构建更加系统化的知识体系。一直以来都很想深入学习一下C++,将其作为自己的主力开发语言。现在为......