【C++】关联式容器

目录

前言:

一,set容器

二,multiset容器

三,map容器

四,multimap容器


前言:

        在C++中,STL中的部分容器,比如:vector、list、deque、 forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。然而,在C++的STL中还存在关联式容器,它也是用来存储数据的,与序列式容器不同的是,其里面存储的是结构的键值对,在数据检索时比序列式容器效率更高。

        键值对用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和 value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。STL中关于键值对的定义:

template <class T1, class T2>
struct pair
{
    typedef T1 first_type;
    typedef T2 second_type;
    T1 first;
    T2 second;
    pair() 
        : first(T1())
        , second(T2())
    {    }
    pair(const T1& a, const T2& b) 
        : first(a)
        , second(b)
    {    }
};

        根据应用场景的不桶,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用二叉搜索树(准确来说是红黑树,即平衡二叉搜索树)作为其底层结果,容器中的元素是一个有序的序列。


一,set容器

set综合使用文档:set的使用

注意:

        1,与map/multimap不同,map/multimap中存储的是真正的键值对,set中只放value,但在底层实际存放的是由构成的键值对。

        2,set中插入元素时,只需要插入value即可,不需要构造键值对。

        3,set中的元素不可以重复(因此可以使用set进行去重)

        4,使用set的迭代器遍历set中的元素,可以得到有序序列

        5,set中的元素默认按照小于来比较

        6,set中查找某个元素,时间复杂度为:log n

        7,set中的元素不允许修改,因为它是一个关联式容器,如果允许修改里面的元素,那么可能会破坏内部排序

        8,set中的底层使用二叉搜索树(红黑树)来实现

set的模板参数列表

T:set中存放元素的类型,实际在底层存储的键值对。

Compare:set中元素默认按照小于来比较。

Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理。(非必要情况可不用管)

set的构造

set的功能

        C++STL容器中很多必要功能都是一样的,如迭代器、反向迭代器、常量迭代器、empty、size等。这里我们只介绍下set与之需要注意的功能接口,具体其它简单的功能查看文档即可。

函数声明功能介绍
pair<iterator, bool> insert(const value_type& x)在set中插入元素x,实际插入的是<x, x>构成的
键值对,如果插入成功,返回<该元素在set中的
位置,true>, 如果插入失败,说明x在set中已经
存在,返回<x在set中的位置,false>
void erase ( iterator position )删除set中position位置上的元素
size_type erase ( const key_type& x ) 删除set中值为x的元素,返回删除的元素的个数
void erase ( iterator first, iterator last )删除set中[first, last)区间中的元素
void swap(set<Key, Compare, Allocator>& st)交换set中的元素
void clear ( ) 将set中的元素清空
iterator find ( const key_type& x ) const 返回set中值为x的元素的位置
size_type count ( const key_type& x ) const 返回set中值为x的元素的个数

set的使用

#include <iostream>

using namespace std;

void settest()
{
    //set不存在相同数据
    set<int> s;
    //插入时不会插入重复数据
    s.insert(5);
    s.insert(5);
    s.insert(1);
    s.insert(1);
    s.insert(9);
    s.insert(2);
    s.insert(3);
    for (auto e : s) {
        cout << e << " ";
    }
    cout << endl;

    cout << s.erase(7) << " " << s.erase(5) << endl; //没有此值,返回假(0)。若存在此值,返回真(1)
    set<int>::iterator its = --s.end();
    s.erase(its); //删除接口为迭代器时没有返回值
    //由于set中没有重复数据,所以count统计时只会返回1或0
    cout << s.count(3) << " " << s.count(9) << " " << s.count(7) << endl; //count返回元素数量

    set<int>::iterator sit = s.begin();
    while (sit != s.end()) {
        //*it += 8; set中的数据不能被修改
        cout << *sit << " ";
    }
    cout << endl;

    set<int>::iterator it = s.find(3);
    if (it == s.end()) {
        cout << "没有找到" << endl;
    }
    else {
        cout << "找到了" << endl;
    }

    cout << endl;
}

int main() {
    settest();
    return 0;
}


二,multiset容器

multiset综合使用文档:multiset的使用

说明:

        1,multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。

        2,在multiset中,元素的value也会识别它(因为multiset中本身存储的就是组成的键值对,因此value本身就是key,key就是value,类型为T)。multiset元素的值不能在容器中进行修改(因为元素总是const的,一旦修改将破坏内部结构)。

注意:

        1,multiset中,底层存储的是键值对。

        2,mulitset与set操作基本一样,与set的区别是,multiset中的元素可以重复,set是中value是唯一的。 

        3,使用迭代器对multiset中的元素进行遍历,可以得到有序的序列。

        4,multiset中的元素不能修改。

        5,在multiset中找某个元素,时间复杂度为O(log N)。

multiset的使用

        此处只简单演示与set的不同,其他接口与set相同。

#include <iostream>

using namespace std;

void multisettest()
{
    //multiset容器可以存在相同数据
    multiset<int> s;
    //插入时可以插入相同数据
    s.insert(5);
    s.insert(5);
    s.insert(1);
    s.insert(1);
    s.insert(9);
    s.insert(2);
    s.insert(3);
    for (auto e : s) {
        cout << e << " ";
    }
    cout << endl;

    cout << s.count(5) << " " << s.count(9) << " " << s.count(7) << endl;  //统计数据数量
    cout << endl;
}

int main() {
    multisettest();
    return 0;
}


三,map容器

map综合使用文档:map的使用

说明:

        1,map是关联容器,它按照特定的次序(按照key来比较)存储,由键值key和值value组合而成的元素。

        2,在map中,键值key通常用于排序和唯一地标识元素(即不可重复),而值value中存储与此键值key关联的内容(即可以重复)。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型 value_type 绑定在一起,为其取别名称为pair: typedef pair value_type。也就是说 map 中的每个元素都是一个 pair 对象。

        3,在内部,map中的元素总是按照键值key进行比较排序的(这里也可修改,需要自己实现)。注意,这里无论如何都不会按value进行排序。

        4,map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。

map的模板参数说明

key:键值对中key的类型

T:键值对中value的类型

Compare:比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比
较,一般情况下(即内置类型元素)该参数不需要传递,如果无法比较时(即自定义类型),需要用户
自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)。

Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的
空间配置器。除非必要,一般不用管。

map接口功能

        由于map内部结构的实现跟set一样,都是二叉搜索树(即平衡二叉搜索树,也叫做红黑树)所以大多数接口都是一样。这里要注意接口的是 "operator[]"。改接口参数是key,返回值是key对应的value,当key不存在时,operator[]用默认value与key构造键值对然后插入,返回该默认value。此接口的实现可理解为以下代码:

V& operator[](const K& key) {
    pair<iterator, bool> p = insert(make_pair(key, V()));
    return ret.first->second;
}

当第一次进行调用时,map[key]的返回值是一个模板的默认构造

当key值已经存在时,插入失败,直接返回value,不会造成任何影响

接口声明接口功能
pair<iterator, bool> insert(const value_type& x)

在map中插入键值对x,注意x是一个键值对,返回

值也是键值对:iterator代表新插入元素的位置,

bool代表释放插入是否成功

void erase(iterator position)删除position位置上的元素
size_type erase ( const key_type& x ) 删除键值为x的元素,返回删除元素的个数
void erase ( iterator first, iterator last ) 删除[first, last)区间中的元素
void swap(map<Key, T, Compare, Allocator>& mp)交换两个map中的元素
void clear ( ) 清空容器元素
iterator find ( const key_type& x )

在map中插入key为x的元素,

找到返回该元素的位置的迭代器,否则返回end

size_type count ( const key_type& x ) const

返回key为x的键值在map中的个数,

注意,map中key是唯一的,

因此该函数的返回值 要么为0,要么为1,

因此也可以用该函数来检测一个key是否在map中

#include <iostream>
#include <string>

#include <map>
using namespace std;

void maptest()
{
    map<string, string> m;
    m.insert(pair<string, string>("apple", "苹果"));

    pair<string, string> p = { "string", "字符串" };
    m.insert(p);

    //make_pair可理解为pair<T1, T2>,是一个函数模板,只是单纯的写法简单
    m.insert(make_pair("sort", "排序")); //C++ 98中不支持多参数隐式类型转换,通常用make_pair
    m.insert({ "vector", "顺序表" });  //C++ 11中支持多参数隐式类型转换(多参数构造函数)

    map<string, string>::iterator it = m.begin();
    while (it != m.end()) {
        //cout << *it << endl;  map存储的元素是pair对象。pair不支持流操作
        cout << (*it).first << " : " << (*it).second << endl;
        //cout << it->first << " : " << it->second << endl;与上等效。但不能使用m.first或m.second进行访问,map内部没有此接口
        it++;
    }
    cout << endl;

    for (auto& e : m) {  //这里建议使用引用,因为map里的元素基础是pair,发生拷贝的代价非常大
        cout << e.first << " : " << e.second << endl;
    }
    cout << endl << endl;
}

void mapuse()
{
    map<string, int> m;
    //注意类型:pair<iterator, bool> insert(const value_type & val); 
    pair<map<string, int>::iterator, bool> p = m.insert(make_pair("sort", 1));
    if (p.second) {  //插入成功时,bool返回1,失败返回0
        cout << p.first->first << " : " << p.first->second << endl;
    }
    else {
        cout << "插入失败" << endl;
    }
    cout << endl;

    m["vector"] = 2; //插入key和value
    m["list"] = 3; 
    m["deque"];  //value调用默认构造,这里为0
    m["list"] = 5;  //修改"list"的value
    cout << m["vector"] << endl; //查找

    for (auto& e : m) {
        cout << e.first << " : " << e.second << endl;
    }
    cout << endl;
}

int main() {
    maptest();

    mapuse();
    return 0;
}


四,multimap容器

multimap综合使用文档:multimap的使用

multimap的用法与map一样,唯一要注意的有两点:

        1,multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复。

        2,multimap中没有重载operator[]操作,因为key有重复的数据,operator[]无法确定value。

这里的map/multimap运用,可参考set/multiset。两者基本是相辅相成的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第五届国际信息技术与教育技术大会(ITET 2024)即将召开!

2024年第五届国际信息技术与教育技术大会&#xff08;ITET 2024&#xff09;将于5月10-12日在日本鸟取举行。本届会议由日本鸟取大学主办&#xff0c;冈山大学、湘南工业大学、名古屋工业大学、山口大学等提供技术支持。ITET 2024旨在探讨计算机领域的创新发展在教育环境中所带…

javase day03笔记

第三天课堂笔记 idea的使用★★★ 创建空工程创建模块创建包&#xff1a;package创建类idea的设置 file -> settings 快捷键 shift &#xff0b; 回车 &#xff1a; 光标切换到下一行psvm回车&#xff1a; main方法main回车&#xff1a;main方法sout回车&#xff1a;输…

快速入门:JS对象/BOM/DOM/事件监听

本贴介绍JS相对进阶的知识&#xff0c;对于JavaScript的基础语法&#xff0c;本文不再赘述~ 一.JavaScript对象 1.Array数组对象 定义 var arr new Array(1,2,3); var arr[1,2,3]; 访问 arr[0]1; Js数组类似Java中的集合&#xff0c;长度&#xff0c;类型都可以改变。 如…

Web端功能测试方法最有作用的5个点

对于web测试&#xff0c;较之其他软件测试又有所不同&#xff0c;这是细节的不同&#xff0c;这个不同需要我们在不停的测试中去总结的。 web测试正式测试之前&#xff0c;应先确定如何开展测试&#xff0c;不可盲目的测试&#xff0c;讲究方法才能行之有效的提高我们的效…

Linux——文件缓冲区与模拟实现stdio.h

前言 我们学习了系统层面上的文件操作&#xff0c;也明白了重定向的基本原理&#xff0c;在重定向中&#xff0c;我们使用fflush(stdout)刷新了缓冲区&#xff0c;当时我们仅仅知道重定向需要刷新缓冲区&#xff0c;但是不知道其所以然&#xff0c;今天我们来见识一下。 一、…

框架学了不会用?四小时做完一个完整的前后端分离demo(SpringBoot+Vue)

四小时做完一个完整的前后端分离demo&#xff08;SpringBootVue&#xff09; 分享一个看到的还不错的小项目&#xff0c;非常适合刚学完框架但是没有太多动手机会的的学生党用来练手。 优势 手把手写代码&#xff0c;有教学视频免费&#xff0c;有源代码项目周期短 视频教程…

Nvidia显卡@参数规格@驱动下载@cuda版本查看

文章目录 Nvidia显卡产品类型GeForce系列 命名规则前缀和后缀技术特点性能指标/&#x1f47a;显存(VRAM)显存和位宽位宽和现存容量的设计 其他 显卡信息查看Nvidia官网查看其他数据库核心规格GeForce系列产品参数在线查看&#x1f47a;大汇显卡规格总比较其他显卡规格比较 性能…

Facebook、亚马逊账号如何养号?

之前我们讨论过很多关于代理器的问题。它们的工作原理是什么?在不同的软件中要使用那些代理服务器?这些代理服务器之间的区别是什么?什么是反检测浏览器等等。 除了这些问题&#xff0c;相信很多人也会关心在使用不同平台的时代理器的选择问题。比如&#xff0c;为什么最好…

目标检测——布匹缺陷检测数据集

一、简要 布匹瑕疵是指在布料生产过程中或后续处理中出现的各种不符合质量标准或期望的缺陷。这些瑕疵可能源自原料、织造工艺、染色、印花、加工等多个环节。布匹瑕疵的类型繁多&#xff0c;涵盖了结构瑕疵和质量瑕疵两大类。结构瑕疵指的是布料本身的缺陷&#xff0c;包括嵌…

Skia最新版CMake编译

运行示例&#xff1a;example/HelloWorld.cpp Skia: 2024年03月08日 master分支: 993a88a663c817fce23d47394b574e19d9991f2f 使用CMake编译 python tools/git-sync-depsbin/gn gen out/config --idejson --json-ide-script../../gn/gn_to_cmake.py此时output目录会生成CM…

指数幂+力扣

题目 题目链接 . - 力扣&#xff08;LeetCode&#xff09; 题目描述 代码实现 class Solution { public:double myPow(double x, int n) {long t n;return t > 0 ? _myPow(x, t) : 1 / _myPow(x, -t);}double _myPow(double x, int n){if(n 0) return 1;double y _…

【解决】Sublime Text找不到Package Control选项,且输入install也不显示Install Package(其中一种情况)

【问题描述】 Sublime Text 找不到 Package Control 选项&#xff0c;且输入 install 也不显示 Install Package 【解决方法】&#xff08;其中一种情况&#xff09; 1、工具栏 Preferences -> Settings&#xff0c;点开查看设置文档 2、检查 "ignored_packages&q…

Vue+OpenLayers7入门到实战:OpenLayers地图鼠标点击事件使用,点击地图后弹框并显示当前位置经纬度

返回《Vue+OpenLayers7》专栏目录:Vue+OpenLayers7入门到实战 前言 本章介绍如何使用OpenLayers7在地图上监听点击事件,以及监听地图点击事件后进行简单弹框并获取当前点击位置的经纬度并显示wgs84坐标位置和度分秒格式经纬度信息。 二、依赖和使用 "ol": "…

【开发】JavaWeb开发中如何解析JSON格式数据

目录 前言 JSON 的数据类型 Java 解析 JSON 常用于解析 JSON 的第三方库 Jackson Gson Fastjson 使用 Fastjson Fastjson 的优点 Fastjson 的主要对象 JSON 接口 JSONObject 类 JSONArray 类 前言 1W&#xff1a;什么是JSON&#xff1f; JSON 指 JavaScrip t对象表…

上手OpenMMLab——从零开始通过mmagic上手AIGC

上手OpenMMLab——从零开始通过mmagic上手AIGC 目录 上手OpenMMLab——从零开始通过mmagic上手AIGC**写在前面****MMagic简介与特性****环境搭建与初步探索****文本生成与编辑****图像生成与风格迁移****音频生成与语音合成****高级应用与案例分享** **总结****附录&#xff1a…

sqli-labs练习

2关 找出数据库名字 从数据库security 中找到表明名: 找到数据库名字: 从表users中找到列: 取出表users用户名和密码:用户名~密码 3关 判断出id是(‘id’)的形式 4关 双引号测试报错,推测是(“id“) 5关 填写id=1没有回显信息(布尔盲注一般适用于页面没有回显字…

力扣--动态规划97.交错字符串

思路分析&#xff1a; 动态规划数组定义&#xff1a; dp[i][j] 表示&#xff1a;使用字符串 s1 的前 i 个字符和字符串 s2 的前 j 个字符&#xff0c;能否构成字符串 s3 的前 i j 个字符的交错组合。 初始化&#xff1a; dp[0][0] 初始化为 1&#xff0c;表示空串是 s1 和 s2 …

蓝桥杯练习系统(算法训练)ALGO-980 斐波那契串

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;10.0s Java时间限制&#xff1a;30.0s Python时间限制&#xff1a;50.0s 问题描述 斐波那契串由下列规则生成&#xff1a;   F[0] "0";   F[1] "1";   F[n] F[n-1] F[n-2]…

2024年最新《国际预警期刊》正式更新!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、国际期刊预警名单的变化&#xff1f;二、课程案例展示&#xff08;篇幅有限仅展示部分&#xff09;1.【热图系列】2.【九象限图系列】3.【富集分析系列】4.【机…

Redis哨兵模式(Sentinel)的搭建与配置

创建三个Redis实例所需的目录,生产环境需独立部署在不同主机上,提高稳定性。 Redis 哨兵模式(Sentinel)是一个自动监控处理 redis 间故障节点转移工作的一个redis服务端实例,它不提供数据存储服务,只进行普通 redis 节点监控管理,使用redis哨兵模式可以实现redis服务端故…
最新文章