C++map的基本操作和使用

我不生产自己不熟悉的内容,我只是陌生内容的搬运工!向原作致敬!原作1,原作2。

1、map简介

map是一类关联式容器,是键-值对的集合,可以理解为关联数组,可以使用键作为下标来获取一个值。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。

2、map的功能

自动建立key - value的对应,key 和 value可以是任意你需要的类型。 根据key值快速查找记录,快速插入key - value记录,快速删除记录,根据key 修改value记录,遍历所有记录。 

3、map对象的定义

使用前添加map头文件,必须分别指明键和值的类型:

map<string,int> word_count;

map的构造函数:

map<k,v>m;   创建一个名为m的空map对象,其键值类型分别为k和v

map<k,v>m(m2);   创建m2的副本m, m与m2必须有相同的键值类型

map<k,v>m(b,e);   创建map类型的对象,存储迭代器b和e标记的范围内所有元素的副本,元素的类型必须能转化为pair<const k,v>

map对象的元素是键-值对,map的value_type反映了这样的事实,value_type是存储元素的键以及值的pair类型,而且键为const,比如word_count的类型为:

pair<const string, int>类型

map类定义的类型:

map<K,V>::key_type  在map容器中,用作索引的键的类型

map<K,V>::mapped_type  在map容器中,键所关联的值的类型

map<K,V>::value_type   一个pair类型,它的first元素具有const map<K,V>::key_type类型,而second元素则为map<K,V>::mapped_type类型

map迭代器进行解引用将产生pair类型的对象

map<string,int>::iterator map_it=word_count.begin();
cout<<map_it->first;
cout<<" "<<map_it->second;
map_it->first="new key" //error
++map_it->second
上边的error在于,对于迭代器来说,可以修改实值(即pair的second),而不能修改key(pair的first)。

map对象是模板类,需要关键字和存储对象两个模板参数:

std:map<int, string> personnel;

这样就定义了一个用int作为索引,并拥有相关联的指向string的指针.

为了使用方便,可以对模板类进行一下类型定义:

typedef map<int, CString> UDT_MAP_INT_CSTRING;

UDT_MAP_INT_CSTRING enumMap;

4、在map中插入元素

改变map中的条目非常简单,因为map类已经对[]操作符进行了重载

enumMap[1] = "One";

enumMap[2] = "Two";

.....

这样非常直观,但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为"Two"; 该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。我们可以用以下方法来避免开销:

enumMap.insert(map<int, CString> :: value_type(2, "Two"));

下边详细总结一下map当中insert的使用:

入单个元素的insert版本使用键-值pair类型的参数,对于参数为一对迭代器的版本,迭代器必须指向键-值pair类型的元素

map容器的接受单个值的insert版本的返回类型

C++map的基本操作和使用_第1张图片

使用下标给map添加新元素,元素的值部分将采用值初始化,而插入元素的另一个方法是:直接使用insert成员,语法更紧凑:

word_count.insert(map<string,int>::value_type("Anna",1));
传递给insert的实参相当的笨拙,可以用两种方法简化:

使用make_pair:

word_count.insert(make_pair("Anna",1));

或使用typedef:
typedef map<string, int>::value_type valtype;
word_count.insert(valtype("Anna", 1))

检测insert的返回值。如果试图插入的元素所对应的键已经在容器中,则insert将不作任何操作(即map当中的键唯一),但是带有一个键-值pair形参的insert版本将返回一个值:包含一个迭代器和一个bool值的pair对象,其中迭代器指向map中具有相应键的元素,而bool值则表示是否插入了该元素。

下面使用insert重写的单词统计程序:

#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<utility>
using namespace std;
int main()
{
    map<string, int> word_count;
    string word;
    while(cin>>word) {
        pair<map<string, int>::iterator, bool> ret=word_count.insert(make_pair(word,1));
        if(!ret.second)
            ++ret.first->second;
    }
    map<string, int>::iterator it;
    for(it=word_count.begin(); it!=word_count.end(); it++) 
        cout<<it->first<<":"<<it->second<<endl;
    return 0;
}

5、查找并获取map中的元素

下标操作符给出了获得一个值的最简单方法:

CString tmp = enumMap[2];

但是,只有当map中有这个键的实例时才对,否则会自动插入一个实例,值为初始化值。

我们可以使用Find()和Count()方法来发现一个键是否存在。

查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key,在这里需要提到的是begin()和end()两个成员,分别代表map对象中第一个条目和最后一个条目,这两个数据的类型是iterator.

int nFindKey = 2; //要查找的Key

//定义一个条目变量(实际是指针)

UDT_MAP_INT_CSTRING::iterator it= enumMap.find(nFindKey);

if(it == enumMap.end()) 

{

//没找到

}

else {

//找到

}

下标操作符读取一个值会产生副作用,map容器提供了两个操作:count和find,用于检查某个键是否存在而不会插入该键

m.count(k)    返回m中k的出现次数

m.find(k)    如果m容器中存在按k索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端迭代器。

1)、使用count检查map对象中某键是否存在

对于map对象,count成员的返回值只能是0或1,map容器只允许一个键对应一个实例,所有count可有效地表明一个键是否存在

map<string, int> word_count;
int occurs=0;
if(word_count.count("foo"))
    occurs=word_count["foo"];

2)、读取元素而又不插入该元素

find操作返回指向元素的迭代器,如果元素不存在,则返回end迭代器

map<string, int> word_count;
int occurs=0;
map<string,int>::iterator it=word_count.find("foo");;
if(it!=word_count.end())
    occurs=it->second;

6、从map中删除元素

移除某个map中某个条目用erase()

该成员方法的定义如下

iterator erase(iterator it); //通过一个条目对象删除 
iterator erase(iterator first, iterator last); //删除一个范围 
size_type erase(const Key& key); //通过关键字删除 
clear()就相当于 enumMap.erase(enumMap.begin(), enumMap.end());





你可能感兴趣的:(C++map的基本操作和使用)