C++:set和map的使用

news2025/2/22 10:51:55

set和map的使用

    • 1.关联式容器
    • 2.key模型和key_value模型
    • 3.set
      • 3.1一些注意点
      • 3.2set的使用
      • 3.3习题
    • 4.multiset
    • 5.map
      • 5.1一些注意点
      • 5.2map的使用
      • 5.3习题
    • 6.multimap

1.关联式容器

序列式容器:比如我们之前讲的vector、string、list等均为序列式容器,特点是按元素顺序来保存和访问

关联式容器:比如本次讲的map和set,和序列式容器不同,其依靠键值来保存和访问,数据检索效率闭序列式容器高。
PS:本文只讲使用,set和map底层是一颗平衡二叉搜索树



2.key模型和key_value模型

(1)key模型:主要解决在不在的问题?比如现在录入人脸信息,用户登录的判断就可以采用key模型,set其实就是一个key模型。

#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
using namespace std;

int main() {
    set<string> s;
    vector<string> v = {"张三", "李四", "王五", "赵六"};
    for (auto e : v) s.insert(e);  //还没讲接口,这里的作用是录入信息
    string input;
    while (cin >> input)
    {
        if (s.count(input))  //这里的作用是在set中查找input是否存在
        {
            cout << "存在,查找成功" << endl;
        }
        else
        {
            cout << "不存在" << endl;
        }
    }
    return 0;
}

在这里插入图片描述

(2)key_value模型:和key模型最大的不同就是存储,key模型只存一个键值,而key_value模型存储的是一个键值对。除了可以解决在不在的问题,还可以通过键值找到对应信息,map其实就是一个key_value模型。

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

//SGI-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)
    {}
};

int main() {
    //还没讲接口,知道大概意思就行
    map<string, string> mapTranslation;  //就以英汉翻译词典为例子
    //录入词典的信息
    mapTranslation.insert(make_pair("left", "左边"));
    mapTranslation.insert(make_pair("right", "右边"));
    mapTranslation.insert(make_pair("sort", "排序"));
    mapTranslation.insert(make_pair("father", "父亲"));
    string input;
    while (cin >> input)
    {
        if (mapTranslation.count(input))  //这里也是查找在不在
        {
            cout <<  "中文为: " << mapTranslation[input] << endl;  //这里拿到value
        }
        else
        {
            cout << "词典无记录" << endl;
        }
    }
    return 0;
}

在这里插入图片描述


3.set

3.1一些注意点

  • set不允许键值冗余,比如插入3后不能再插入3。拒绝键值冗余,本就是二叉搜索树的定义。故set中不会有重复的元素,可以利用这一点对数据进行去重
  • set利用迭代器遍历元素,可以得到一个有序序列,可利用这一点对数据进行排序。原理是中序遍历二叉搜索树可以得到有序序列。
  • set元素默认按小于比较,即默认升序。
  • set不允许修改元素,如果支持修改会无法维护搜索二叉树的结构。
  • set中查找某个元素,时间复杂度为:logN

3.2set的使用

(1)模板参数
在这里插入图片描述

(2)构造

函数声明功能
set (const Compare& comp = Compare(), const Allocator& = Allocator())空构造
set (InputIterator first, InputIterator last, 后面和空构造一样)迭代器区间构造
set (const set& x)拷贝构造

(3)迭代器

函数声明功能
iterator begin()返回set中起始位置元素的迭代器
iterator end()返回set中最后一个元素后面的迭代器
reverse_iterator rbegin()反向迭代器,返回end()
reverse_iterator rend()反向迭代器,返回begin()的前一个位置

(4)容量

函数声明功能
bool empty ( ) const检测set是否为空,空返回true,否则返回false
size_type size() const返回set中有效元素的个数

(5)增加、删除、查找

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

几个注意点:

  • insert的返回值希望大家记一下,方便大家理解map的核心接口。
  • 判断键值在不在set中有两种方法
    第一种是find(key),依据返回值判断,是end()代表不在,否则存在。
    第二种是count(key),如果存在返回非0,不存在返回0,也可以进行判断。
    选择习惯的方式即可。

3.3习题

链接:两个数组交集
题目要求:
在这里插入图片描述

代码加解析:

//主要思想是利用set进行去重
//(1)先用set1存储nums1的值,比如[1,2,2,1]->[1,2](set去重)
//(2)定义一个set2,如果nums2的值在set1中可以找到,就插入set2中
//注意:因为nums2中可能存在多个相同值,故用set可以进行去重
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        set<int> set_exist;
        set<int> result;
        for(auto e : nums1)
        {
            set_exist.insert(e);
        }
        for(auto e : nums2)
        {
            if(set_exist.find(e) != set_exist.end()) //如果存在
            {
                result.insert(e);
            }
        }
        return vector<int>(result.begin(), result.end());
    }
};

//这个题也可以先去重加排序
//交集:(1)不相等小的加加;(2)相等是交集,同时加加
//差集:(1)不相等小的是差集,小的加加;(2)相等都不是差集,同时加加 (3)一方走完,剩下的都是差集



4.multiset

multiset和set使用几乎一致,唯一的不同就是允许键值冗余。

  • 迭代器遍历依然可以得到有序序列
  • count()接口对multiset非常重要
  • multiset的find()查找返回的是中序遍历的第一个元素
  • multiset可以对存在重复元素的序列排序。



5.map

5.1一些注意点

  • 在内部,map中的元素总是按照键值key进行比较排序的,和value无关。
  • map不允许键值冗余,map中的键值对是唯一的。
  • 利用迭代器遍历可以得到有序序列,不过是按key来排序
  • map不允许修改key,但可以修改value。支持修改键值会无法维护二叉搜索树结构。
  • map中查找某个元素,时间复杂度为:logN

5.2map的使用

(1)模板参数
在这里插入图片描述

(2)构造

函数声明功能
map (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type())空构造
map (InputIterator first, InputIterator last, 后面和空构造一样)迭代器区间构造
map (const map& x)拷贝构造

(3)迭代器

函数声明功能
iterator begin()返回set中起始位置元素的迭代器
iterator end()返回set中最后一个元素后面的迭代器
reverse_iterator rbegin()反向迭代器,返回end()
reverse_iterator rend()反向迭代器,返回begin()的前一个位置

(4)容量

函数声明功能
bool empty ( ) const检测set是否为空,空返回true,否则返回false
size_type size() const返回set中有效元素的个数

(5)增加、删除、修改、查找

函数声明功能
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 )
删除map中键值为x的元素,返回删除的元素的个数
void erase
( iterator first, iterator last )
删除map中[first, last)区间中的元素
iterator find
( const key_type& x ) const
返回map中键值为x的元素的迭代器,不存在返回end()
size_type count
( const key_type& x ) const
返回map中键值为x的元素的个数
mapped_type& operator[]
(const key_type& k)
非常重要
返回key对应的value
void swap ( map& mp )交换两个map中的元素
void clear ( )将map中的元素清空

几个注意点:

  1. 这里的接口中最重要的就是operator[],因为[]不仅可以访问value,还可以进行插入
    operator[]的原理是: 用<key, T()>构造一个键值对,然后调用insert()函数将该键值对插入到map中如果key已经存在,插入失败,如果不存在就进行插入。insert返回的键值对第一个元素就是元素对应的迭代器,operator[]函数通过迭代器最后返回键值对中的value的引用。
  2. 对map的迭代器解引用得到是键值对结构体,设迭代器为x,拿value的方式有两种。(*x).secondx->second
  3. map判断键值对在不在的方式和前面set一致

5.3习题

链接:前k个高频单词
题目要求:
在这里插入图片描述
代码加解析:

//这里的核心思路:
//(1)用map统计每个字符串出现次数
//(2)对键值对进行排序,出现次数相同的要按字典序来排
//     因为键值对自带的比较规则是只按key排序的,所以我们需要自定义排序(比较方法)
//其实只是访问的话unordered_map更加快速,但unordered_map迭代器遍历无法保证有序
class compare
{
public:
    bool operator()(pair<string,int> p1, pair<string,int> p2) const
    {
        if(p1.second == p2.second)
        {
            //出现次数相同,按字典序排
            return p1.first < p2.first;
        }
        else
        {
            //要排降序,按大于排
            return p1.second > p2.second;
        }
    }
};
class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string, int> count_map;  //用map统计
        for(int i = 0; i < words.size(); i++){
            count_map[words[i]] ++;
        }
        //排序(降序)
        vector<pair<string,int>> result(count_map.begin(), count_map.end());;
        sort(result.begin(),result.end(),compare());
        vector<string> ret;
        for(int i = 0; i < k; i++)
            ret.push_back(result[i].first);
        return ret;
    }
};
//也可以利用set进行排序
// set<pair<string, int>, compare> sort_set(count_map.begin(), count_map.end());
// vector<string> ret;
// auto it = sort_set.begin();
// while(k--)
// {
//     ret.push_back(it->first);
//     it++;
// }
// return ret;



6.multimap

multimap和map使用几乎一致,最大的不同就是允许键值冗余

  • multimap没有支持operator[]
    原因是存在多个同键值的键值对,不知道取谁的value。
  • 迭代器遍历依然可以得到有序序列。
  • count()接口对multimap非常重要。
  • multimap的find()查找返回的是中序遍历的第一个元素
  • multimap可以对存在重复元素的序列排序。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

回归预测 | Matlab实现MPA-BP海洋捕食者算法优化BP神经网络多变量回归预测

回归预测 | Matlab实现MPA-BP海洋捕食者算法优化BP神经网络多变量回归预测 目录 回归预测 | Matlab实现MPA-BP海洋捕食者算法优化BP神经网络多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现MPA-BP海洋捕食者算法优化BP神经网络多变量回归预测&…

重新思考边缘负载均衡

本文介绍了Netflix在基于轮询的负载均衡的基础上&#xff0c;集成了包括服务器使用率在内的多因素指标&#xff0c;并对冷启动服务器进行了特殊处理&#xff0c;从而优化了负载均衡逻辑&#xff0c;提升了整体业务性能。原文: Rethinking Netflix’s Edge Load Balancing[1] 我…

全功能测试框架 - Carina

Carina是一个基于Java的测试自动化框架&#xff0c;它将所有测试层结合在一起&#xff1a;移动应用程序&#xff08;web、本机、混合&#xff09;、web应用程序、REST服务和数据库。 github&#xff1a;GitHub - zebrunner/carina: Carina automation framework (TestNG): Web…

MySQL(7):单行函数

不同DBMS函数的差异 内置函数&#xff1a; 系统内置的通用函数。 自定义函数&#xff1a; 根据自己的需要编写的函数。 大多数 DBMS 使用&#xff08;||&#xff09;或者&#xff08;&#xff09;来做拼接符&#xff0c;而在 MySQL 中的字符串拼接函数为concat()。 大部分 D…

【rust/esp32】初识slint ui框架并在st7789 lcd上显示

文章目录 说在前面关于slint关于no-std关于dma准备工作相关依赖代码结果参考 说在前面 esp32版本&#xff1a;s3运行环境&#xff1a;no-std开发环境&#xff1a;wsl2LCD模块&#xff1a;ST7789V2 240*280 LCDSlint版本&#xff1a;master分支github地址&#xff1a;这里 关于s…

asp.net docker-compose添加dapr配置

docker-compose.yml添加配置 webapplication1-dapr:image: "daprio/daprd:1.9.6"network_mode: "service:webapplication1"depends_on:- webapplication1 docker-compose.override.yml中添加 dapr-placement:command: ["./placement", "-po…

Nacos 注册中心如何做到每秒百万级别的服务注册?

1. Nacos 注册中心如何做到每秒百万级别的服务注册 &#xff1f; 在 nacos.io 官方文档里边有这样一个性能测试报告&#xff1a; PS&#xff1a;TPS 是指每秒能够处理的事物数 / 任务数 从图中可以看出当有 4 台机器&#xff0c;并发数为 100 的时候&#xff0c;注册实例的测…

SpringSecurity全家桶 (一) —— 简介

1. 概述 Spring Security 是一个框架&#xff0c;提供针对常见攻击的身份验证、授权和保护。 它为保护命令式和响应式应用程序提供了一流的支持&#xff0c;是保护基于 Spring 的应用程序的事实标准。 2. 了解 shiro&#xff1a; 在之前SSM框架盛行的时代&#xff0c;项目的…

在maven官网中如何下载低版本的maven

链接&#xff1a;https://archive.apache.org/dist/maven/maven-3/

万宾科技管网水位监测助力智慧城市的排水系统

以往如果要了解城市地下排水管网的水位变化&#xff0c;需要依靠人工巡检或者排查的方式&#xff0c;这不仅加大了人员的工作量&#xff0c;而且也为市政府带来了更多的工作难题。比如人员监管监测不到位或无法远程监控等情况&#xff0c;都会降低市政府对排水管网的管理能力&a…

汇编语言(举个栗子)

汇编语言&#xff08;Assembly Language&#xff09;是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言&#xff0c;亦称为符号语言。在汇编语言中&#xff0c;用助记符代替机器指令的操作码&#xff0c;用地址符号或标号代替指令或操作数的地址。在不同…

物理机安装黑群晖

物理机安装黑群晖 黑群晖系统: DSM 6.2.0–6.2.3 引导版本: 1.04b (首选推荐版本) 针对机型: DS918 引导方式: 引导方式&#xff1a;传统BIOS和UEFI&#xff08;可选&#xff09; 点击此处链接&#xff0c;引导下载地址 点此处为&#xff1a;DS918 DSM 6.2.3-25426 Update2 系…

【LeetCode:421. 数组中两个数的最大异或值 | 位运算 贪心】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【漏洞复现】Drupal XSS漏洞复现

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 复现环境&#xff1a;Vulhub 环境启动后&#xff0c;访问 http://192.168.80.141:8080/ 将会看到drupal的安装页面&#xff0c;一路默认配置下一步安装。因为没有mysql环境&#xff0c;…

JavaEE平台技术——预备知识(Web、Sevlet、Tomcat)

JavaEE平台技术——预备知识&#xff08;Web、Sevlet、Tomcat&#xff09; 1. Web基础知识2. Servlet3. Tomcat并发原理 1. Web基础知识 &#x1f192;&#x1f192;上个CSDN我们讲的是JavaEE的这个渊源&#xff0c;实际上讲了两个小时的历史课&#xff0c;给大家梳理了一下&a…

鲁棒性的含义以及如何提高模型的鲁棒性

1、含义 鲁棒是Robust的音译&#xff0c;也就是健壮和强壮的意思。它也是在异常和危险情况下系统生存的能力。比如说&#xff0c;计算机软件在输入错误、磁盘故障、网络过载或有意攻击情况下&#xff0c;能否不死机、不崩溃&#xff0c;就是该软件的鲁棒性。所谓“鲁棒性”&am…

蓝桥杯官网填空题(方格填数)

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 在 2 行 5 列的格子中填入 1 到 10 的数字。 要求&#xff1a; 相邻的格子中的数&#xff0c;右边的大于左边的&#xff0c;下边的大于上边的。 如下图所示的 …

项目实战:在首页上添加分页按钮

1、在index.html添加div_pagination <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href"style/index.css"><script src&qu…

设置IDEA快捷生成方法头,类头注释

1.File->settings->editor->live templates进入Live Template界面进行设置&#xff1a; 下一步&#xff1a; 下一步&#xff1a; /*** Title: $title$* author: sunyanzeng* date: $datatime$*/在需要添加文件头的地方打出“aa”&#xff0c;回车&#xff0c;会自…