C++ map的使用

本文介绍了C++ STL中的map容器,讲解了如何插入键值对,包括使用pair和make_pair,以及通过operator[]修改value。还探讨了erase和find函数的使用,强调了map底层的红黑树特性,使得查找效率高。最后展示了三种统计字符串数组中单词出现次数的方法。
摘要由CSDN通过智能技术生成


map

map虽然翻译过来是图,但是底层是一颗红黑树。

一、insert

map是一个模板类,有两个模板参数,分别对应key和value,习惯性称为键值对。我们这样定义一个map,

#include <iostream>
using namespace std;//map在stl中,所以这两句必不可少

int main()
{
   map<int, int> m; //一个key-value是 int-int的map
    return 0;
}

我们这样插入,

m.insert(2, 2);

(1) pair

但是我们发现编译失败,因为如果你想返回map中的键值对,那就是返回两个值,but C++中没有return两个值的手段(据我所知),所以stl把map的键值对封装在了一个pair中。还有一点,我觉得是为了stl的容器的统一性,有数学的美感。(我猜的)

template<class T1, class T2>//pair的源码大概就是这样
struct pair
{
   typedef T1 first_type;
   typedef T2 second_type;
   
   T1 first;
   T2 second;
   pair(const T1& _first = T1(), const T2& _second = T2())
   :first(_first)
   ,second(_second)
   {}
};

pair简言之,就是封装两个类型,pair除了map可以用,凡是需要封装两个类型的地方都可以用(好像是废话)。从这里我们也可以看出C++的封装性,我们也可以偷学,多用封装。

m.insert(pair<int, int>(2, 2));//这样插入
m.insert(make_pair(3, 3));//有时候也喜欢这样插入

make_pair就是一个模板函数,构造一个pair的对象。

template<class T1, class T2> //像这样,
pair<T1, T2> make_pair(const T1& _first, const T2& _second)
{
   return pair<T1, T2>(_first, _second);
}

还有下面这样的插入方法,

m.insert(map<int, int>::value_type(4, 4));
//value_type实际上就是pair的类型

还有一种方法,我们放到后面介绍。

二、erase && find

这两个都很easy,我们就放到一起say。

1.erase

map<int, int>::iterator it = m.begin();
m.erase(it);//可以传迭代器
m.erase(2);//也可以直接传key值

但是传的迭代器必须保证是有效迭代器,而传key值随意传。(即使这个key值不存在)

find

map<int, int>::iterator it = m.find(2);
//find会返回一个迭代器,如果key值不存在,返回最后一个结点的下一个位置,
//就是 m.end().
if(it == m.end()) //没找到
cout << "no such data" << endl;

这里有一个小的Q:
为什么map要专门写一个find函数,不用算法库里面的find呢?
map底层是红黑树!使用专门的find函数搜索效率 O(logN),而算法库的效率是O(N)。

三, operator[]

map中的key是不能改变的,表面上你传的是 map<int, int>,实际上是map<const int, int> 。
从这一点我们也能看出来,map中的value是可以改动的。而operator[ ]就提供了改动value的方法。使用方法如下:

map<int, int> m;
m.insert(make_pair(2, 2));
m[2] = 3;//key == 2,原来map中有,则只会改变value的值为2.
m[3] = 1; //key == 3 的值原来map中没有,那么会插入这个pair,然后将value改成1.

operator[ ]的参数是key值,它会根据你传入的key值,再利用value的默认构造函数构造一个pair出来,然后将这个pair插入map,并且返回value的引用。如果key值在map中已经存在,那么只会返回value的引用。

最后来一个有意思的东西,统计次数。给定一个数组,里面有各种英文单词,统计每个单词出现的次数。

string str[] = {"CS","DN","CS","CSDN","CS","CSDN","CS"};
map<string, int> counMap;

//方法1
for(auto& e : str)
{
   map<string, int>::iterator it = countMap.find(e);
   if(it != countMap.end())//key值存在,那么对应的value++
    it->second++; //operator->()
    else
    countMap.insert(make_pair(e, 1));//key值不存在,插入对应的string和value。
}

//方法2
for(auto& e : str)
{
pair<map<string, int>::iterator, bool> pr = countMap.insert(make_pair(e, 1));
 if(pr.second == false)//key值已存在
 {
    pr.first->second++; //value++
 }
}

//方法3
for(auto& e : str)
{
   countMap[e]++;
}
//如果e已存在,那么对应的value++,
//如果e不存在,那么插入e,初始化value为0,最后++

(全文完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值