概念简述
Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。(PS:此处特别说明:map内部的数据是有序的,默认情况下是按照key值升序排序的)它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。
功能简述
-
自动建立Key - value的对应。key 和 value可以是任意你需要的类型。
-
根据key值快速查找记录,查找的复杂度基本是Log2(N)。
-
快速插入Key -Value 记录。
-
快速删除记录
-
根据Key 修改value记录。
-
遍历所有记录。
下面就以一道例题来简述map的一些基本操作:
map的使用
——例:洛谷P1308 [NOIP2011 普及组] 统计单词数
题意简述:给定一个单词,在指定的文章中去寻找这个单词出现了几次(不区分大小写),以及第一次出现单词的位置。
解题思路
首先,输入的是两个字符串,第一行是给定的字符,第二行是所要检索的文章。如何进行匹配是个问题。第一步肯定是将文章拆分成单词存储起来,这样后面进行检索匹配时才比较容易。
此时,有人可能会想到用数组来存储数据,让每个单词的位置作为数组下标、单词作为内容存储起来,可是数组的大小不容易确定,会造成存储空间的浪费。所以,就想到了使用map来建立单词在文章中的位置和单词本身之间的联系。
- 在使用map之前首先要包含其头文件
- 定义一个map对象,map对象是模板类,需要关键字和存储对象两个模板参数。
#include <map>//包含相应头文件
map<int,string> answer;//定义一个map对象,<关键词的类型,value的类型>
一、拆分文章并存储
此题我使用string中的substr()函数将文章中的单词拆分出来。
并且在拆分的过程中就将拆分出来的单词存储在了map中。
- 此处使用了一种较为简单的插入数据的方法,此方法有点类似于数组的插入方法,[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:本题中的一些易错点的总结:
- 读入带有空格的字符串用getline()函数;
- 将读入的单词与文章统一变为小写或者大写,以达到题目要求的统计不区分大小写,使用transform()函数,(要包含algorithm头文件);
- 使用substr()函数来拆分文章(要包含string头文件);
- 注意输出时只输出给定单词第一次在文章中出现时的首字母的位置。