STL库——map的学习和使用

概念简述

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。(PS:此处特别说明:map内部的数据是有序的,默认情况下是按照key值升序排序的)它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。

功能简述

  1. 自动建立Key - value的对应。key 和 value可以是任意你需要的类型。

  2. 根据key值快速查找记录,查找的复杂度基本是Log2(N)。

  3. 快速插入Key -Value 记录。

  4. 快速删除记录

  5. 根据Key 修改value记录。

  6. 遍历所有记录。

下面就以一道例题来简述map的一些基本操作:

map的使用

——例:洛谷P1308 [NOIP2011 普及组] 统计单词数

题目描述
题意简述:给定一个单词,在指定的文章中去寻找这个单词出现了几次(不区分大小写),以及第一次出现单词的位置。
输入输出
说明提示

解题思路

首先,输入的是两个字符串,第一行是给定的字符,第二行是所要检索的文章。如何进行匹配是个问题。第一步肯定是将文章拆分成单词存储起来,这样后面进行检索匹配时才比较容易。
此时,有人可能会想到用数组来存储数据,让每个单词的位置作为数组下标、单词作为内容存储起来,可是数组的大小不容易确定,会造成存储空间的浪费。所以,就想到了使用map来建立单词在文章中的位置和单词本身之间的联系

  1. 在使用map之前首先要包含其头文件
  2. 定义一个map对象,map对象是模板类,需要关键字和存储对象两个模板参数。
#include <map>//包含相应头文件
map<int,string> answer;//定义一个map对象,<关键词的类型,value的类型>

一、拆分文章并存储
此题我使用string中的substr()函数将文章中的单词拆分出来。
并且在拆分的过程中就将拆分出来的单词存储在了map中。

  1. 此处使用了一种较为简单的插入数据的方法,此方法有点类似于数组的插入方法,[index]中的index就是关键字,=后面的是value值。
int index=0;
    for(int i=0; i<arti.size(); i++){
        if(arti[i]==' '){
            answer[index]=arti.substr(index,i-index);//将数据存入map中
            index=i+1;
        }
    }
    answer[index]=arti.substr(index);//此处将最后一个单词存入了map;

二、遍历map并进行比对
一般有两种方法来对map进行遍历:
第一种:应用前向迭代器。
第二种:应用反相迭代器。
我采用的是前向迭代器,反向迭代器其实与前向迭代器的写法类似,只不过是起始位置不同而已。

map<int,string>::iterator iter;//声明一个迭代器
    for(iter = answer.begin(); iter != answer.end(); iter++){//从头到尾前向迭代
        if((iter->second==word)&&(flag==true)){
            sum++;
            num=iter->first;
            flag=false;
        }
        else if(iter->second==word) sum++;
    }

此处也附上反向迭代器的写法:

 map<int, string>::reverse_iterator iter; //注意这里与上面的前向迭代器不同哦 
  
    for(iter = answer.rbegin(); iter != answer.rend(); iter++)  //从尾部往首部遍历
  
        cout<<iter->first<<"  "<<iter->second<<endl;  
  
  • 此处附上map中常用的函数:(本题中用到的函数标有*)
    begin() * 返回指向map头部的迭代器

    clear() 删除所有元素

    count() 返回指定元素出现的次数

    empty() 如果map为空则返回true

    end() * 返回指向map末尾的迭代器

    equal_range() 返回特殊条目的迭代器对

    erase() 删除一个元素

    find() 查找一个元素

    get_allocator() 返回map的配置器

    insert() 插入元素

    key_comp() 返回比较元素key的函数

    lower_bound() 返回键值>=给定元素的第一个位置

    max_size() 返回可以容纳的最大元素个数

    rbegin() 返回一个指向map尾部的逆向迭代器

    rend() 返回一个指向map头部的逆向迭代器

    size() * 返回map中元素的个数

    swap() 交换两个map

    upper_bound() 返回键值>给定元素的第一个位置

    value_comp() 返回比较元素value的函数

下面附上本题的完整AC代码:

#include <iostream>
#include <map>
#include <string>
#include <algorithm>
using namespace std;

int main() {
    string word,arti;
    getline(cin,word);
    transform(word.begin(),word.end(),word.begin(),::tolower);
    int sum=0,num;
    bool flag=true;
    map<int,string> answer;
    getline(cin,arti);
    transform(arti.begin(),arti.end(),arti.begin(),::tolower);
    int index=0;
    for(int i=0; i<arti.size(); i++){
        if(arti[i]==' '){
            answer[index]=arti.substr(index,i-index);
            index=i+1;
        }
    }
    answer[index]=arti.substr(index);
    map<int,string>::iterator iter;
    for(iter = answer.begin(); iter != answer.end(); iter++){
        if((iter->second==word)&&(flag==true)){
            sum++;
            num=iter->first;
            flag=false;
        }
        else if(iter->second==word) sum++;
    }
    if(sum==0) cout<<"-1";
    else{
        cout<<sum<<" "<<num;
    }
    return 0;
}

PS:本题中的一些易错点的总结:

  1. 读入带有空格的字符串用getline()函数;
  2. 将读入的单词与文章统一变为小写或者大写,以达到题目要求的统计不区分大小写,使用transform()函数,(要包含algorithm头文件);
  3. 使用substr()函数来拆分文章(要包含string头文件);
  4. 注意输出时只输出给定单词第一次在文章中出现时的首字母的位置。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值